Zalgorithm

Copy a directory and its contents from the command line

To copy a directory and its contents, the general command is:

cp [options] source_directory destination_directory

But the cp command with no options can only be used for copying files, not directories. The common flags/options for copying directories are:

As always, look at the man pages:

❯ man cp

CP(1)                         User Commands                         CP(1)

NAME
       cp - copy files and directories

SYNOPSIS
       cp [OPTION]... [-T] SOURCE DEST
       cp [OPTION]... SOURCE... DIRECTORY
       cp [OPTION]... -t DIRECTORY SOURCE...

DESCRIPTION
       Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

       Mandatory  arguments  to  long options are mandatory for short op‐
       tions too.

       -a, --archive
              same as -dR --preserve=all

# ...

       -d     same as --no-dereference --preserve=links
# ...

       --preserve[=ATTR_LIST]  # note that --preserve=all is valid
              preserve the specified attributes
# ...
       -R, -r, --recursive
              copy directories recursively
# ...

The cp command can create the destination directory

When copying a directory and its contents, cp will create the destination directory if it doesn’t exist:

~
❯ mkdir foo

~
❯ cp -a foo/ bar

Attempting to copy a directory with cp without setting options

Attempting to copy a directory with cp without setting any options will result in an error:

~
❯ rmdir bar

~
❯ cp foo/ bar
cp: -r not specified; omitting directory 'foo/'

Copy only the contents of a directory

To copy only the contents of a source directory into an existing directory, use a trailing /. or /* after the source directory path. Note that the destination directory must exist for this to work:

~
❯ mkdir foo

~
echo "this is a test" > foo/foo.txt

❯ mkdir bar

~
echo "this is another test" > bar/bar.txt

~
❯ cp -a foo/. bar/

~
❯ ls bar
Permissions Size User    Date Modified Name
.rw-r--r--    21 scossar  9 Jan 10:03   bar.txt
.rw-r--r--    15 scossar  9 Jan 10:02   foo.txt

Additional details

What are file attributes?

File attributes are metadata associated with a file. Things like permissions, file size, ownership, date modified, links (symlinks).

What does the no-dereference flag do?

The --no-dereference flag (shorthand -P when used with cp) in general, causes the utility (in this case cp) to operate on the symbolic link itself rather than the file or directory it points to.

When --no-defererence (shorthand -P) is used with cp, when a symbolic link is encountered in the source directory, cp copies the symbolic link — it creates an identical symlink at the destination — instead of copying the content of the file that the link points to.

The entry for -P in the cp man page makes this a little clearer:

-P, --no-dereference
      never follow symbolic links in SOURCE

The -d flag is equivalent to --no-dereference --preserve=links. The --preserve=links flag tells cp to preserve hard links.

The -d flag (or --no-dereference --preserve=links) tells cp to preserve hard links.

Comparing the two when copying a directory that contains hard links (files that were linked with ln instead of ln -s):

I’m not entirely following the how hard links are handled by these options, or even the appropriate use case for hard links, other than creating them accidentally by using ln without the -s flag.

References

“cp(1) — Linux manual page,” https://man7.org/linux/man-pages/man1/cp.1.html .