This is one of the most basic tasks you can do.
But it’s fraught with complexity.
The obvious requirement here is
I want to copy a directory exactly as it is from A to B.
So, let’s try this on the Mac (note: this will be different if you’re on Linux):
I had symlinks so I got:
cp: some/directory/structure: No such file or directory
COMPATIBILITY Historic versions of the cp utility had a -r option. This implementation supports that option; however, its use is strongly discouraged, as it does not correctly copy special files, symbolic links, or fifo's.
cp -r does not copy symlinks.
Note: I use
tldr which incorrectly says:
- Copy a folder recursively to another location: cp -r path/to/folder path/to/copy
-a Same as -pPR options. Preserves structure and attributes of files but not directory structure.
Why? ‘cos if we look at
-P If the -R option is specified, no symbolic links are followed. This is the default.
So that’s not going to work.
OK, moving on. Let’s look at
-R. Seems more like it.
-R If source_file designates a directory, cp copies the directory and the entire subtree connected at that point. If the source_file ends in a /, the contents of the directory are copied rather than the directory itself. This option also causes symbolic links to be copied, rather than indirected through, and for cp to create spe- cial files rather than copying them as normal files. Created directories have the same mode as the corresponding source direc- tory, unmodified by the process' umask. In -R mode, cp will continue copying even if errors are detected. Note that cp copies hard-linked files as separate files. If you need to preserve hard links, consider using tar(1), cpio(1), or pax(1) instead.
On a large directory this took forever though. As an alternative, let’s try:
Hmm. Measuring the time this took on a large directory (
rsync was 50% slower.
Should you have a trailing slash? On the source directory? The destination directory? Both? None?
You need the trailing slash on the source directory but the destination is optional. i.e. both of these work:
cp -R source/ destination/
cp -R source/ destination
cp -R source destination
source into the
cp -R source/* destination
would not copy
dot files to
A trailing / at the end of a pathname forces the pathname to refer to a directory.