How do you copy a directory?

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):

cp -r 

I had symlinks so I got:

cp: some/directory/structure: No such file or directory

Let’s check man cp.

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.

so 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 -Pwe see:

 -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:

rsync -pvzar

Hmm. Measuring the time this took on a large directory (14 G), rsync was 50% slower.


More notes:

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

but this:

cp -R source destination

would copy source into the destination directory.


cp -R source/* destination

would not copy dot files to destination.


A trailing / at the end of a pathname forces the pathname to refer to a directory.


Leave a Reply

Your email address will not be published. Required fields are marked *