I understand that this is useful. But I'm a bit confused because it seems this feature breaks standards.
cp behavior when copying recursively from a/.
to b
is perfectly consistent with its "normal" behavior.
By default, cp's doesn't create parent directories. This can be modified with the parents switch:
--parents
use full source file name under DIRECTORY
But what does that mean?
It means that while the command
cp --parents -r some/path/to/source dest
will copy the source directory's contents into dest/some/path/to/source
, the command
cp -r some/path/to/source dest
will copy the source directory's contents into dest/source
.
Likewise, the command
cp -r some/path/to/source/. dest
will copy the source directory's contents into dest/.
, which is just dest
.
I thought a
and a/.
is the same path.
a
and a/.
is the same path. But as an argument to cp, it is just a string.
Note that the commands
cp --parents -r some/path/to/source dest
and
cd some/path/to && cp --parents -r source dest
will behave differently as well.
What about cp -r a/inner/.. b
? Taking into account your explanation, should not it copy files to b/..
(i.e. to the current directory)?
Well, yes. This is an exception.
At least in the GNU version of cp, there is a special case for for the ..
basename.
From coreutils-8.22/src/cp.c
:
if (parents_option)
{
[removed]
}
else
{
char *arg_base;
/* Append the last component of 'arg' to 'target_directory'. */
ASSIGN_BASENAME_STRDUPA (arg_base, arg);
/* For 'cp -R source/.. dest', don't copy into 'dest/..'. */
dst_name = (STREQ (arg_base, "..")
? xstrdup (target_directory)
: file_name_concat (target_directory, arg_base,
NULL));
}
The motivation seems to be to avoid copying outside the destination folder, which – while perfectly consistent with cp's behavior in every other case – is a little counterintuitive and could have unpleasant consequences.
After all, I don't think anybody would expect the command
cp -r .. ~
to affect files outside his home directory...
1
cp a b
doesn't copy a directory called "a" to a new directory called "b" in Ubuntu. It outputscp: omitting directory 'a'
and does nothing. You have to use the-r
option (or something that implies it, such as-a
) to copy directories. – Wyzard – 2014-03-04T20:54:49.783Sorry, I've missed the
-r
option in examples, but I use it on real task. Fixed. Thanks for the note. – raacer – 2014-03-05T01:00:03.073