1. Overview
In this tutorial, we'll learn how to copy a file to multiple directories on Linux. The commands will work on any POSIX shell, including bash.
2. To A Single Directory
We can use the cp command to copy files to a single directory quite simply:
cp source1 source2 ... directory
cp takes only a single destination directory, though.
So, how can we copy a file to multiple directories?
2. Shell Loop
Let's try repeating the copy command using a loop. This will copy the favicon.ico file to both dir-1 and dir-2:
for i in dir-1 dir-2; do cp favicon.ico ${i}/; done
The slash after the i variable ensures that we copy to a directory and not a file. The curly braces are not required, but they may help with readability.
3. Dealing with Special Characters
Let's see how to handle more exotic filenames.
We should keep in mind that on Linux all kinds of characters are allowed in filenames. That includes whitespace, punctuation marks, and even emojis and newlines. Anything, except for slash and null characters, could show up in filenames.
These names will wreak havoc in our shell scripts if we don't quote them properly.
Let's use quoted filenames and quote the i variable:
for i in "I'm a directory!" 'Another directory'; do cp favicon.ico "${i}/"; done
4. Wildcard Matching
What if we want to provide destination directories dynamically, using some search criteria?
For example, let's copy our favicon file to all directories inside /var/www, but only ones ending in staging, like /var/www/recipe-site-staging:
find /var/www -maxdepth 1 -iname '*staging' -type d -exec cp -- favicon.ico '{}' ';'
find will search /var/www for directories as specified.
In this example, we're looking for directories that are directly inside /var/www and not multiple levels down, by using -maxdepth 1. This makes sure that, for example, /var/www/site-staging will match, but /var/www/static/site-staging will not.
-iname is the case insensitive pattern of the directory names we're looking for, where * is a wildcard character.
-exec is a handy parameter that indicates what command to run on each directory.
And the command we want to run is cp — favicon.ico <directory-name>. The double dash is for terminating cp‘s option list. This makes sure that a directory named something like –force can't accidentally act as an option for the cp command.
The curly braces indicate where to place the directory name in our command. We indicate the end of our command with a semi-colon.
Note that we've got our curly braces and semi-colon in single quotes so they don't get shell-interpreted.
5. Conclusion
We learned how to copy a file to multiple directories for both predefined and wildcard inputs.