Linux – The cp command


To totally unlock this section you need to Log-in


One of the most common command to use (and need to be used) on Linux systems, especially when working on CLI only systems (with no GUI installed), is the cp (copy) command. The following section of this article will show several common and advanced ways to use cp command on Linux systems on files and folders.

The general syntax for the cp command is as follows:

cp [OPTIONS] SOURCE... DESTINATION

  • The SOURCE can contain one or more files or directories as arguments, and the DESTINATION argument can be a single file or directory.
  • When the SOURCE and DESTINATION arguments are both files, the cp command copies the first file to the second one. If the file doesn’t exist, the command creates it.
  • When the SOURCE has multiple files or directories as arguments, the DESTINATION argument must be a directory. In this situation, the SOURCE files and directories are moved to the DESTINATION directory.
  • When the SOURCE and DESTINATION arguments are both directories, the cp command copies the first directory into the second one.
  • To copy files and directories, you must have at least read permissions on the source file and write permission on the destination directory. Otherwise, a permission denied error is shown.

A more complete view about the syntax of the cp command is shown below; let's note that the cp command have also simple backup/sync capabilities, with --backup and --update options, for example, so it can be used also even in, a bit, more complex scenarios and in scripted solutions.

Usage: cp [OPTION]... [-T] SOURCE DEST
  or:  cp [OPTION]... SOURCE... DIRECTORY
  or:  cp [OPTION]... -t DIRECTORY SOURCE...
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

Mandatory arguments to long options are mandatory for short options too.
  -a, --archive                same as -dR --preserve=all
      --attributes-only        don't copy the file data, just the attributes
      --backup[=CONTROL]       make a backup of each existing destination file
  -b                           like --backup but does not accept an argument
      --copy-contents          copy contents of special files when recursive
  -d                           same as --no-dereference --preserve=links
  -f, --force                  if an existing destination file cannot be
                                 opened, remove it and try again (this option
                                 is ignored when the -n option is also used)
  -i, --interactive            prompt before overwrite (overrides a previous -n
                                  option)
  -H                           follow command-line symbolic links in SOURCE
  -l, --link                   hard link files instead of copying
  -L, --dereference            always follow symbolic links in SOURCE
  -n, --no-clobber             do not overwrite an existing file (overrides
                                 a previous -i option)
  -P, --no-dereference         never follow symbolic links in SOURCE
  -p                           same as --preserve=mode,ownership,timestamps
      --preserve[=ATTR_LIST]   preserve the specified attributes (default:
                                 mode,ownership,timestamps), if possible
                                 additional attributes: context, links, xattr,
                                 all
      --no-preserve=ATTR_LIST  don't preserve the specified attributes
      --parents                use full source file name under DIRECTORY
  -R, -r, --recursive          copy directories recursively
      --reflink[=WHEN]         control clone/CoW copies. See below
      --remove-destination     remove each existing destination file before
                                 attempting to open it (contrast with --force)
      --sparse=WHEN            control creation of sparse files. See below
      --strip-trailing-slashes  remove any trailing slashes from each SOURCE
                                 argument
  -s, --symbolic-link          make symbolic links instead of copying
  -S, --suffix=SUFFIX          override the usual backup suffix
  -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY
  -T, --no-target-directory    treat DEST as a normal file
  -u, --update                 copy only when the SOURCE file is newer
                                 than the destination file or when the
                                 destination file is missing
  -v, --verbose                explain what is being done
  -x, --one-file-system        stay on this file system
  -Z                           set SELinux security context of destination
                                 file to default type
      --context[=CTX]          like -Z, or if CTX is specified then set the
                                 SELinux or SMACK security context to CTX
      --help     display this help and exit
      --version  output version information and exit

Copying Files with cp Command

The most basic scenario of using cp is to copy a file in the current working directory. For example, to copy a file named file.txt to file_backup.txt, you wound run the following command:

cp file file_backup

or:

cp file{,_backup}

To copy a file to another directory, specify the absolute or the relative path to the destination directory.

When only the directory name is specified as a destination, the copied file has the same name as the original file.

In the following example, we are copying the file file.txt to the /backup directory:

cp file.txt /backup

Same as the above command, in the following example we are using the slash-dot (/.), that is implied, instead, in the above form of the command. The dot is a special file in every Linux directory which means "this directory".

cp file.txt /backup/.

If we want to copy every file in the working directory whose name begins, for example, with sample into the directory /directory/subdirectory we can use a wildcard. The asterisk ("*") is a wildcard - a special character which expands to match other characters. Specifically, the asterisk wildcard matches zero or more non-whitespace characters. For instance, this command will copy any files named file, sample001, sample.txt, sampleone.jpg, sample-archive.zip, etc.

cp sample* /directory/subdirectory

If you want to copy the file under a different name, you need to specify the desired file name. The command below will copy the file to the specified directory as new_file.txt.

cp file.txt /backup/new_file.txt

By default, if the destination file exists, it is overwritten. The -n (no clobber) option tells cp not to overwrite an existing file.

To force cp to prompt for confirmation, use the -i option.

cp -i file.txt file_backup.txt

If you want to copy the file only if it is newer than the destination, invoke the command with the -u option:

cp -u file.txt file_backup.txt

When copying a file, the new file is owned by the user running the command. Use the -p option to preserve the file mode, ownership , and timestamps:

cp -p file.txt file_backup.txt

Another option that can be useful is -v, which tells cp to print verbose output:

cp -v file.txt file_backup.txt

'file.txt' -> 'file_backup.txt'

Copying Directories with cp Command

To copy a directory, including all its files and subdirectories, use the -R or -r (recursive) option.

In the following example, we are copying the directory Pictures to Pictures_backup:

cp -R Pictures Pictures_backup

The command above creates the destination directory and recursively copy all files and subdirectories from the source to the destination directory.

If the destination directory already exists, the source directory itself and its content are copied inside the destination directory.

To copy only the files and subdirectories but not the source directory, use the -T option:

cp -RT Pictures Pictures_backup

Another way to copy only the directory’s content but not the directory itself is to use the wildcard character (*). The disadvantage of the following command is that it does not copy the hidden files and directories (the ones starting with a dot .):

cp -RT Pictures/* Pictures_backup/

All the options we used in the previous section when copying files can also be used when copying directories. The main difference is that when copying directories, you always need to use the -R option.

Copy Multiple Files and Directories

To copy multiple files and directories at once, specify their names and use the destination directory as the last argument:

cp file.txt dir file1.txt  dir1

When copying multiple files, the destination must be a directory.

To copy multiple directories, in the following example multiple folders with a common name part (sample), in a destination directory we can use the following approach, using again the recursive option:

ls | grep sample
sample1
sample2
sample3
cp -r sample* final/

Copy a file to multiple directories

Another, not so common but highly possible, is to copy a file to multiple directories.

Let's say that we have a have text file called test-config.conf in our home directory, and we want to copy it to two different directories called Downloads and Documents in one go.

We can copy a single file to multiple directories at once using find and cp commands.

The find is a Unix and Linux command to search for files in a directory hierarchy and the cp command, obviously, is used to copy files and directories.

We can copy a file named test-config.conf to ~/Downloads and ~/Documents directories we can use the following approach:

$ find ~/Downloads/ ~/Documents/ -maxdepth 0 -type d -exec cp test-config.conf {} \;

The above command will copy test-config.conf file in the current directory to the ~/Downloads and ~/Documents directories.

If we don't specify -maxdepth 0 option, the test-config.conf file will be copied to ~/Downloads, ~/Documents directories and also into their sub-directories as well.

Finally, if there is any file already present with the same name (i.e test-config.conf) in any of the destination directories, the above command will simply overwrite the existing file without any confirmation (the cp default behavior). We can override this action by using cp -n in the above example.

Another way, using the cp command, to copy a file in multiple target directories is to combine it with echo and xargs commands, as shown below (xargs command is used to build and execute command lines from standard input):

$ echo ~/Downloads ~/Documents | xargs -n 1 cp test-config.conf

The echo command prints the given string or text to the standard output. In this case, we pipe (pass) the output of the echo command to xargs. Here, echo command will send the directory path to xargs as input.

xargs command, at this point, runs the cp command two times and appends the path of each directory on to the end of the cp command.

The xargs commands receives two arguments (in this case the two directory paths) from echo command. The -n 1 option on the xargs command tells the xargs to only append one of those arguments at a time, so basically it will run the cp command two times respectively with the two different paths.

Creating backup of existing destination file while copying

Default behavior of cp command is to overwrite the file on destination if the same file exists, if you want to make a backup of existing destination file during the copy operation then use --backup option, example is shown below:

cp --backup=simple -v /home/example/distributions.txt /mnt/backup/distributions.txt
'/home/example/distributions.txt' -> '/mnt/backup/distributions.txt' (backup: '/mnt/backup/distributions.txt~')

If you have noticed, backup has been created and appended tilde symbol at end of file. Backup option accept following parameters:

none, off  – never make backups
numbered, t – make numbered backups
existing, nil – numbered if numbered backups exist, simple otherwise
simple, never – always make simple backups

Now we could consider and example by using --backup=numbered. Let's consider a working test1.py script and that we want to make a backup of it before adding the next component. We decide to use the backup option with numbering, as follows:

cp --force --backup=numbered test1.py test1.py
ls
test1.py  test1.py.~1~

The --backup=numbered option says, "I want to do a backup, and I want successive backups to be numbered" So the first backup will be number 1, the second 2, and so on.

Second, note that the source file and destination file are the same. Normally, if we try to use the cp command to copy a file onto itself, we will receive a message like:

cp: 'test1.py' and 'test1.py' are the same file

In this case we would use the --force option.

Third, we used the ls (or "list") command to show that we now have a file called test1.py, which is the original, and another called test1.py.~1~, which is the backup file.

Suppose now that we want to add to the program another print statement that prints the string "hello also to you". Now the test1.py content will look like:

print 'hello world'
print 'hello also to you'

If we again execute the backup step, here's what happens:

cp --force --backup=numbered test1.py test1.py
ls
test1.py test1.py.~1~ test1.py.~2~

Now we have two backup files: test1.py.~1~, which contains the original one-line program, and test1.py.~2~, which contains the two-line program, and we can move on to adding and testing some more functionality.

Preserve mode, ownership and timestamps while copying

If we want to preserve the file attributes like mode, ownership and timestamps while copying then we can use -p option in cp command, as follows:

cp -p devops.txt /mnt/backup/
ls -l devops.txt
-rw-r--r-- 1 root root 37 Feb  5 20:02 devops.txt
ls -l /mnt/backup/devops.txt
-rw-r--r-- 1 root root 37 Feb  5 20:02 /mnt/backup/devops.txt

Do not follow (or follow) symbolic links in Source while copying

If you do not want to follow the symbolic links of source while copying then use -P option in cp command, example is shown below

ls -l /opt/example-release.txt
lrwxrwxrwx 1 root root 14 Feb  9 12:28 /opt/example-release.txt -> example-release.txt
cp -P example-release.txt /mnt/backup/
ls -l /mnt/backup/example-release.txt
-rw-r--r-- 1 root root 35 Feb  9 12:29 /mnt/backup/example-release.txt

Note: Default behavior of cp command is to follow the symbolic links in source while copying.

If we want, instead, to copy/preserve symbolic links while using the cp command we could use the following approach (if we are copying a symbolic file link):

cp --preserve=links example-release.txt /mnt/backup/

If we are copying symbolic links inside a specific folder (and subfolders and files included in it), it is recommended to use the -a (the same as -dR --preserve=all) option to be able to copy symbolic links properly (and also subfolders and files).

NOTE: the symbolic links will be copied only if none of the symlinks are to relative paths.

Create a simple incremental backup approach

Finally, we could consider, for example on DEV or TEST environments, using cp command to make incremental backup of folders by using the following approach, in which -Ruv specifies a recursive copy (R), updating only newer files available in $source (u) and enabling verbose mode (v) and finally put the command ouput into /var/logs/userbackups.log file:

cp -Ruv $source $destination > /var/logs/userbackups.log

Additionally, we could consider, to keep only previous versions of the updated files we could integrate the above command with the --backup option, as shown below:

cp -Ruv --backup=numbered $source $destination > /var/logs/userbackups.log


Summary
Article Name
Linux - The cp command
Description
One of the most common command to use (and need to be used) on Linux systems, especially when working on CLI only systems (with no GUI installed), is the cp (copy) command. The following section of this article will show several common and advanced ways to use cp command on Linux systems on files and folders.
Author
Publisher Name
Heelpbook.net