Americas

  • United States
sandra_henrystocker
Unix Dweeb

How to copy files to multiple locations on Linux

How-To
Sep 08, 20225 mins
Linux

You can run a series of Linux commands to copy multiple files to a folder or copy a single file to multiple folders, but you can save time and trouble by using xargs, loops and scripts.

data files
Credit: Dell

Using a series of commands to copy a file to multiple locations or a number of files to a single location can be time-consuming, but there are options to speed up the process. This post explains some of them.

Multiple commands like these can to copy a single file to a series of directories on your system:

$ cp myfile dir1
$ cp myfile dir2
$ cp myfile dir3

One way to make the task easier is typing the first command and then repeat the command by only specifying the needed changes. This method relies on whether the file or directory names are similar enough to substitute only some portion of the names.

# single file to multiple dirs        # multiple files to single dir
$ cp myfile dir1                      $ cp myfile1 dir
$ ^1^2^                               $ ^1^2^
cp myfile dir2                        cp myfile2 dir
$ ^2^3^                               $ ^2^3^
cp myfile dir3                        cp myfile3 dir

Another option is to use the xargs command to copy your file to multiple directories:

$ echo dir1 dir2 dir3 | xargs -n 1 cp -v myfile
'myfile' -> 'dir1/myfile'
'myfile' -> 'dir2/myfile'
'myfile' -> 'dir3/myfile'

In this case, the xargs command uses the information you provide (the directory names) to compose each of the three commands required to copy the files to the three directories. The -v argument ensures that you will see a list of the files being copied. The -n ensures that each command will use only one of the arguments provided by the echo command in each of the commands that xargs runs. As a comparison, if you ran a command like this, you would see three arguments per line:

$ echo Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec | xargs -n 3
Jan Feb Mar
Apr May Jun
Jul Aug Sep
Oct Nov Dec

One limitation of using xargs to run multiple commands is that the arguments you send to the command using echo will always be tacked to the end of the command that is run, so you can’t use the same technique to copy three files to a single directory. The cp command requires that the final string be the target directory and there’s no way to get xargs to rearrange the commands. Clearly something like the command below will not work.

$ echo file1 file2 file3 | xargs -n 2 cp dir1
cp: target 'file2' is not a directory
cp: -r not specified; omitting directory 'dir1'

If you tried a command like the one below, you’d also run into problems. Only the last directory in the list would get a copy of the file.

$ cp xyz dir1 dir2 dir3
cp: -r not specified; omitting directory 'dir1'
cp: -r not specified; omitting directory 'dir2'

Another option is to use a for command like one of these to loop through the files:

$ for file in file1 file2 file3        $ for file in `ls file?`
> do                                   > do
>   cp -v $file dir1                   >   cp -v $file dir1
> done                                 > done
'file1' -> 'dir1/file1'                'file1' -> 'dir1/file1'
'file2' -> 'dir1/file2'                'file2' -> 'dir1/file2'
'file3' -> 'dir1/file3'                'file3' -> 'dir1/file3'

Again, the -v is used to display the activities of the cp command so that you can easily see that the command is doing what you expect.

You could also use a command similar to what you see above to copy multiple files into your current or into another directory.

$ for file in myfile1 myfile2 myfile3
> do
>   cp -v $file backups
> done
'myfile1' -> 'backups/myfile1'
'myfile2' -> 'backups/myfile2'
'myfile3' -> 'backups/myfile3'

If you update important files frequently and want to save the files into a backups folder, you should probably turn this command into a script, making it even less likely that you’ll mistype a command and certainly making the process a lot simpler.

#!/bin/bash

for file in myfile1 myfile2 myfile3
do
  cp -v $file backups
done

A script like the one below would take any files you list as arguments and copy them to your backups folder. The file names, however, cannot contain blanks since each string is treated as a separate filename.

#!/bin/bash

if [ $# != 0 ]	# if file names provided
then
  for file in $*
  do
    cp -v $file backups
  done
fi

Running a script through cron would allow you to automatically back up the files that are updated. To check if crontab is installed on your system, try a command like this:

$ which crontab
$ crontab -l
bash: crontab: command not found...

This command will check if cron is installed on Fedora:

$ rpm -q cronie
package cronie is not installed

Cronie is the package that supplies cron and related services. To install it on Fedora, us a command like this:

$ sudo dnf install cronie

After that, you can check on the crontab command like this:

$ which crontab
/usr/bin/crontab

If you don’t have a crontab file yet established, you will see this when you try to look at it:

$ crontab -l
No crontab for username

If you do, you will see something like this showing the commands that have been set up and when they are to be run.

$ crontab -l
0 0 23 * * /usr/bin/cp /home/username/bin/cpfiles

In the above example the cpfiles script will be run at 11 p.m.  every evening provided the crontab daemon (crond) is running.

Wrap-Up

There are certainly many ways to copy a series of files without having to type each cp command or filename separately. Using the xargs command, loops, and scripts can save you a lot of time and trouble.

sandra_henrystocker
Unix Dweeb

Sandra Henry-Stocker has been administering Unix systems for more than 30 years. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She lives in the mountains in Virginia where, when not working with or writing about Unix, she's chasing the bears away from her bird feeders.

The opinions expressed in this blog are those of Sandra Henry-Stocker and do not necessarily represent those of IDG Communications, Inc., its parent, subsidiary or affiliated companies.