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
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) .