CP Coreutils – Added Value of the -T Option in GNU cp and mv

coreutilscp

Why do some GNU Coreutils commands have the -T/--no-target-directory option? It seems like everything that it does can be achieved using the semantics of the . (self dot) in a traditional Unix directory hierarchy.

Considering:

cp -rT /this/source dir

The -T option prevents the copy from creating a dir/source subdirectory. Rather /this/source is identified with dir and the contents are mapped between the trees accordingly. So for instance /this/source/foo.c goes to dir/foo.c and so on, rather than to dir/source/foo.c.

But this can be easily accomplished without the -T option using:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

Semantically, the trailing dot component is copied as a child of dir, but of course that "child" already exists (so doesn't have to be created) and is actually dir itself, so the effect is that /this/path is identified with dir.

It works fine if the current directory is the target:

cp -r /this/tree/node/. . # node's children go to current dir

Is there something you can do only with -T that can rationalize its existence? (Besides support for operating systems that don't implement the dot directory, a rationale not mentioned in the documentation.)

Does the above dot trick not solve the same race conditions that are mentioned in the GNU Info documentation about -T?

Best Answer

Your . trick can only be used when you're copying a directory, not a file. The -T option works with both directories and files. If you do:

cp srcfile destfile

and there's already a directory named destfile it will copy to destfile/srcfile, which may not be intended. So you use

cp -T srcfile destfile

and you correctly get the error:

cp: cannot overwrite directory `destfile' with non-directory

If you tried using the . method, the copy would never work:

cp: cannot stat `srcfile/.`: Not a directory
Related Question