100

I have tried to copy a file test.txt to multiple directories with one command:

cp ~/test.txt ~/folder1 ~/folder2

But I didn't succeed. Is there a way to do that in one command so I can copy a file or even a folder to multiple directories?

5
  • Not easily. You may want to look into "rsync" for efficiently updating multiple existing copies of a folder Mar 13, 2014 at 10:15
  • 3
    Try learning a bit of bash-script. It can get very useful: for dest in folder1 folder2; do cp ~/test.txt ~/"$dest"; done
    – Shahbaz
    Mar 13, 2014 at 11:08
  • 1
    Not a single command but might just help some people who stumble upon here: cp ~/test.txt ~/folder1 && cp ~/test.txt ~/folder2 Nov 5, 2016 at 14:19
  • Duplicate of stackoverflow.com/a/195972/2097284. Aug 11, 2017 at 21:31
  • @ManuJärvinen comment may look flippant but it raises an important point. Why complicate your script? Two separate lines with a single copy is much more readable than all the other answers. I have not used tee much so if I saw the accepted answer in a script, I would have no idea what it was doing. I accept the answers are inventive but in a real world scenario you need simple. Feb 14, 2020 at 8:54

10 Answers 10

98

cp can copy from multiple sources, but can't copy to multiple destinations. See man cp for more info.

The only bash command that I know which can copy/save to multiple destinations is tee.

You can use it in your case as follows:

tee ~/folder1/test.txt ~/folder2/test.txt < ~/test.txt

Note that tee also writes the input to the standard output (stdout). So if you don't want this, you can prevent it by redirecting standard output to /dev/null as follow:

tee ~/folder1/test.txt ~/folder2/test.txt < ~/test.txt >/dev/null
12
  • 14
    Clever, that's cheating! :)
    – terdon
    Mar 11, 2014 at 17:13
  • 5
    +1, clever! And if you use the >/dev/null works with binary files too, without messing up the terminal...
    – Rmano
    Mar 11, 2014 at 17:30
  • 1
    +1 for you , your always ma man :) , but what if i want to copy a directory ?
    – nux
    Mar 11, 2014 at 18:36
  • 2
    @nux Don't forget to use -r option with cp in case of directories Mar 11, 2014 at 19:08
  • 4
    @nux: tee unlike cp copies only file's content ignoring its mode, ownership, timestamps. To avoid repeating the filename: f=text.txt; <~/$f tee ~/folder1/$f > ~/folder2/$f
    – jfs
    Mar 13, 2014 at 9:26
78

Another way to achieve a copy to multiple locations is the following command :

find dir1 dir2 -exec cp file.txt {} \;

If dir1 or dir2 have sub-directories that you don't want the file copied into, add -maxdepth 0option :

find dir1 dir2 -maxdepth 0 -exec cp file.txt {} \;

Note that this will overwrite every file in dir1 and dir2 with file.txt's contents, in addition to copying it. To only copy file.txt without affecting other files in these directories, tell find to only act on directories:

find dir1 dir2 -type d -exec cp file.txt {} \;
11
  • 4
    Nice solution! Seems to me more perfect than with tee.
    – Danatela
    Mar 11, 2014 at 17:55
  • 1
    Indeed, no redirection is involved and it's still one command. Mar 11, 2014 at 18:03
  • 2
    @SylvainPineau In fact there are 3: one is find and for two times (in this case) cp. Not to say that find need a lot of time. Mar 11, 2014 at 18:13
  • 3
    If the definition of a "command" is an "exec" call, maybe, but this is "one command" in my book.
    – kojiro
    Mar 11, 2014 at 22:27
  • 2
    I keep coming back to this one, so thought I should give an upvote :D
    – Jonathan
    Nov 13, 2015 at 12:46
42

The command

cp ~/test.txt ~/folder1 ~/folder2

tries to copy two files (~/test.txt and ~/folder1) to the destination folder2. (And if ~/folder2 exists and is a directory you will have an "omitting directory" warning).

If you want to make multiple copies of the file test.txt, you have to use a loop or multiple commands...

for i in ~/folder1 ~/folder2; do cp  ~/test.txt $i; done 

(...and be careful if you have spaces embedded in the file names, you'll need quoting).

To copy whole directories you have to use the -r option:

for i in ~/folder1 ~/folder2; do cp -r ~/folder3 $i; done

this will create ~/folder1/folder3 and ~/folder2/folder3 with all the files included.

(Learnt 8 years further down the line: notice that you must be careful with spaces in file names. If you have them, change $i with "$i", and be careful about quoting them).

4
  • 1
    For the passing reader: According to the spec, a for loop is a compound command. Therefore this is still one command, and meets all the requirements for the question.
    – kojiro
    Mar 11, 2014 at 22:35
  • @nux, I do not agree on the corrections. 1) the two capitals are wrong, my intent was to interleave the commands into the phrase. 2) the ellipsis is a matter of style; please let my style in.
    – Rmano
    Mar 13, 2014 at 16:06
  • 1
    ok , am sorry man , i thought it will look better .
    – nux
    Mar 13, 2014 at 16:09
  • on my system, it doesnt save folder3 as ~/folder1/folder3, but rather copies everything in folder3 into folder1
    – alpha_989
    Sep 15, 2017 at 23:05
32

You can create a help script , or you can do it with xargs and a print function (in this case, echo ):

echo firstDir secondDir | xargs -n 1 cp test

This will make each directory as an argument to the cp function , using test file as a parameter.

1
  • 3
    This is probably the best/most direct answer to the question
    – Bryson S.
    Jun 22, 2018 at 16:48
11

After a long search this work like a Charm also !

for dir in *; do [ -d "$dir" ] && cp /path/file.txt "$dir" ; done

This will copy file.txt to every directory in your current location in terminal.

for dir in *; do [ -d "$dir" ] && cp -rf /path/folder "$dir" ; done

This will copy a folder to every sub directory in your current location in terminal.

I share it hope it helps others too .

5
  • In zsh, you can use for i in *(/); ... to loop over all the subdirectories, so you can avoid the [ -d ... test. Extended globbing is one of the reason I like it over bash.
    – Rmano
    Mar 12, 2014 at 2:43
  • can your right the code again in a command
    – nux
    Mar 12, 2014 at 12:13
  • 2
    In zsh, the first command of this answer can be simplified as for dir in *(/); do cp /path/file.txt "$dir"; done. See zsh.sourceforge.net/Intro/intro_2.html
    – Rmano
    Mar 12, 2014 at 14:01
  • 6
    You can eliminate the test in any Bourne derived shell with for dir in */; Mar 13, 2014 at 8:05
  • @nux This works really well and the command is very easy to follow. It should be voted much higher!
    – nukeguy
    Jul 15, 2016 at 16:44
0

If you want to copy the file test.txt in every directory in /tmp/target/ ...

create a test environment:

mkdir /tmp/target
cd /tmp/target
mkdir -v {folder1,folder2,folder3}
touch test.txt

copy it:

find * -maxdepth 0 -type d -exec cp -vi test.txt {} \;
0

Just thought to give a variation to the answer of Sylvain Pineau

where dir1 and dir2 are not in your current directory.

find ./ -maxdepth 2 -type d -name dir1 -exec cp file.txt {} \;

here find will look for dir1 two levels deep or you can leave out -maxdepth parameter to find dir1 in all folders in current directory and below it.

0

For files only without preserving attributes. Great if you're copying huge files and only want to read them once:

cat file1 >file2 >file3

For files or directories

xargs -n 1 cp file1 <<< 'file2 file3'
xargs -n 1 cp -r dir1 <<< 'dir2 dir3'
0

I needed to post html index files in the home directory of 10 newly created sub-domains. I created a file with the markup called sites-index and placed it in my working directory and another called sites-home that contained a list of full paths to the copied files on each line (eg /var/path/to/site1/public_html/index.html).

After a bit of searching here I lighted on the following bash script:

while read file; do cp sites-index "$file"; done < sites-home

The script loops through the list, copies the html file at each iteration and sets each line in the list as the new path to which the html is copied.

To run in terminal, type sudo -i to start a root shell (enter your password when prompted). Execute the script.

Alternatively, you can save the command in a text file, for example index.sh and invoke it by typing at the terminal prompt, sudo bash index.sh.

If you run the script without sudo you'll see a list of the files that weren't created due to insufficient permission. If it executes correctly your files will be created without notice.

1
  • 1
    cp has a --verbose or -v flag which I find useful for scripts. One can also do a dry run with echo before the command ( do echo cp ...) and then remove the echo if the list is as expected, though running without sudo is also a convenient test for this particular scenario.
    – Zanna
    Jan 24, 2022 at 11:08
0

parallel cp foo {} ::: */ will copy foo to all the directories in the current directory in parallel:

$ cd "$(mktemp --directory)"
$ mkdir a 'b c'
$ touch foo
$ parallel cp foo {} ::: */
$ ls --recursive 
.:
 a  'b c'   foo

./a:
foo

'./b c':
foo

Useful if you want to do this quickly. Just remember that you need to quote the command or double-escape, for example:

$ cd "$(mktemp --directory)"
$ mkdir 'a b' 'c d' 'e f'
$ touch 'a b/foo'
$ parallel "cp 'a b/foo' {}" ::: 'c d' 'e f'
$ ls --recursive 
.:
'a b'  'c d'  'e f'

'./a b':
foo

'./c d':
foo

'./e f':
foo

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .