Have a look at the commands as they are actually executed:
$ set -x; cp -r ../* .
+ cp -r ../child ../dir1 ../dir2 ../dir3 ../file1 ../file2 ../file3 .
cp: cannot copy a directory, '../child', into itself, './child'
$ set -x; cp -r .. .
+ cp -r .. .
cp: cannot copy a directory, '..', into itself, '.'
Both of your commands attempt to copy a directory into itself, causing a loop. A cp
implementation may detect it, and stop at some point, or keep copying indefinitely (for instance, GNU and BusyBox cp
stops; FreeBSD cp
keeps copying until it hits the file name length limit; similarly, cp
on MacOS keeps copying, as this other question on U&L seems to suggest).
In any case, recursively copying a directory into itself will eventually stop with an error.
Assuming the question is about GNU cp
(the one you likely have on a GNU/Linux system), in the general case your second command (cp -r .. .
) will copy (an unpredictable?) part of the tree rooted in ..
, detect a loop and stop with an error, without any further processing of anything in that tree.
On the other hand, in your first command (cp -r ../* .
), cp
is given eight separate arguments. While the copy of child
's content into child
fails, the other directories and files are copied without issues because none of them contains child
itself.
Note, however, that this won't "work" as intended on systems whose cp
doesn't detect loops and keeps recursively copying.
As a safer approach, to copy all the content of the parent directory into the current directory (child
), excluding the current directory itself, you may use:
$ shopt -s nullglob dotglob extglob
$ cp -r ../!(child) .