cp -H vs cp -L (What is a "command-line" symbolic link?)

Solution 1:

There's no such thing as a command-line symbolic link. The man page refers to links that occur on the command line, i.e., as arguments to the cp command.

Without the -R switch, the behavior of cp -H and cp -L is identical.

With the -R switch, cp -H only dereferences symbolic links that occur in the cp command itself, while -L also dereferences symbolic links inside the recursively copied directories.

The command

cp -R -H source/ dest/

will copy the directory source and all its contents inside the directory dest. If source is a symlink to a directory, cp will dereference the symlink, i.e., copy the directory source points to. However, if cp encounters any symlinks in source's subdirectories, it will create symlinks in the destination folder.

The command

cp -R -L source/ dest/

behaves similarly. However, it will also dereference symlinks in source's subdirectories, i.e., copy the files those symlinks point to.

Solution 2:

The -H option to cp modifies the behavior of -R (recursive copy) as follows:

If -H is not passed, and the source path given on the command line is a symbolic link to a directory, then the link will be copied to the destination path.

If -H is passed, and the source path &c., &c., then the link will be dereferenced, and the referenced directory recursively copied to the destination path.

That doesn't help much, I think; perhaps an example will clarify it better. (In ls -pF output, a trailing / indicates a directory, while a trailing @ indicates a symbolic link.)

1  me@box tmp $ for dir in foo bar; do mkdir $dir; done
2  me@box tmp $ ls -pF
bar/ foo/
3  me@box tmp $ touch foo/file
4  me@box tmp $ ln -s foo baz
5  me@box tmp $ ls -pF
bar/ baz@ foo/
6  me@box tmp $ cp -R baz bar
7  me@box tmp $ ls -pF bar
baz@
8  me@box tmp $ unlink bar/baz
9  me@box tmp $ cp -HR baz bar
10 me@box tmp $ ls -pFR bar
bar:
baz/

bar/baz:
file
11 me@box tmp $

See how that works? At line 6, I issued cp -R without the -H option, and the symbolic link baz got copied into bar/. Then, at line 9, I issued cp -HR, and cp dereferenced baz and recursively copied its contents (i.e., the contents of foo/, as per line 4) into bar/.