When the last argument to
cp is an existing directory,
cp copies the source file(s) into that directory.
mv does the same.
You would like to merge the source directory with the target directory. But that would only make sense when the source is a directory. So when you run
cp somefile existing-directory/, you end up with
existing-directory/somefile; and when you run
cp -r somedir existing-directory/ you end up with
existing-directory/somedir. The behavior that you find intuitive (but which I don't) would require that
cp makes a difference depending on whether the source is a directory or not, so
cp -r somefile somedir existing-directory/ would create
existing-directory/somefile but not
cp something existing-directory copies the source into the target directory. If the source is a directory and you want to copy its contents, run
cp -rp something/* existing-directory/
Note that this omits files whose name begins with a
.. If you want to include them, an easy way is to use
rsync -a something/ existing-directory/
rsync, if you put a
/ at the end of the source, then the source's content is copied into the destination directory. Without a trailing
/ on the source, the source is created as an entry in the destination directory.