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?
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It only takes a minute to sign up.
Sign up to join this communitycp
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
>/dev/null
works with binary files too, without messing up the terminal...
-r
option with cp
in case of directories
Mar 11, 2014 at 19:08
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
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 0
option :
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 {} \;
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
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).
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.
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 .
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
.
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
for dir in */;
Mar 13, 2014 at 8:05
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 {} \;
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.
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'
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.
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.
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
for dest in folder1 folder2; do cp ~/test.txt ~/"$dest"; done
cp ~/test.txt ~/folder1 && cp ~/test.txt ~/folder2
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.