Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This question is a sequel of sorts to my earlier question, Creating numerous directories using mkdir.

I am using the bash shell. I have created fifty directories, each starting with the prefix "s", using the command:

mkdir $(printf "s%02i " $(seq 1 50))

which pads to the second digit with zeros. That is, the directories that I obtain are of the form s01, s02, ..., s49, s50.

Now I would like to use cp to copy a single file (for example, test.txt) to each of the fifty directories. Is it possible to do this in a way analogous to that above? For example, would the following work? I am relatively new to Unix/Linux, so I don't really want to try this until someone please gives me an indication that it is safe.

cp test.txt $(printf "s%02i.txt " $(seq 1 50))

Looking at the man page for cp, it does not look like cp supports multiple destinations like this, however:

NAME
       cp - copy files and directories

SYNOPSIS
       cp [OPTION]... [-T] SOURCE DEST
       cp [OPTION]... SOURCE... DIRECTORY
       cp [OPTION]... -t DIRECTORY SOURCE...

DESCRIPTION
       Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

       Mandatory  arguments  to  long  options are mandatory for short options
       too.
share|improve this question

4 Answers 4

up vote 6 down vote accepted

If you wanted to use the output from your command to copy the file to each directory using cp, you could always pipe it to xargs:

printf "s%02i " $(seq 1 50) | xargs -n 1 cp test.txt

There shouldn't be any concerns about the safety of parsing the output since you know its format and content before hand--the risk of encountering meta characters and space in file names isn't really an issue here.

Alternatively, assuming the directories already exist, you could try something like:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -print0 | xargs -0 -I {} cp test.txt {}

or with no pipe:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -exec cp test.txt {} \;

The last two commands will find any files in the current directory and cp test.txt to them. The -maxdepth 1 option will avoid any sub directories receiving the file as well. Be warned that 's[0-9][0-9]' is matching against s followed by any two digits, which means if for some reason you have s99 in the cwd, it will also receive a copy of test.txt.

share|improve this answer

According to this: http://stackoverflow.com/questions/195655/how-to-copy-a-file-to-multiple-directories-using-the-gnu-cp-command it is not possible to copy one file to multiple destinations. Check the link, as it shows another way to do this.

share|improve this answer

You could also use GNU parallel. Assuming your are in the directory containing text.txt and your 50 dirs are located in /my/50dirs/path (like /my/50dirs/path/s01, /my/50dirs/path/s02 etc) you would run:

seq -w 01 50 | parallel -j1 cp text.txt /my/50dirs/path/s{}
share|improve this answer
2  
Better make that parallel -j1, otherwise there will be one job per core, and on a multicore machine the jobs will compete for IO. –  Gilles Sep 24 '12 at 23:39

You can also let the shell do the iterations with a for loop. This is the most basic way that doesn't rely on external tools like parallel or xargs, and I find it easiest to understand:

for name in $(printf "s%02i " $(seq 1 50)); do
    mkdir $name
    cp test.txt $name
done

There are a million other ways to write this, e.g.:

for name in $(seq -w 1 50); do
    mkdir s$name
    cp test.txt s$name
done

If you want to verify what would be executed before doing it, you can do something like prepending the commands with echo, which will print the line rather than executing it:

for name in $(seq -w 1 50); do
    echo mkdir s$name
    echo cp test.txt s$name
done

outputs:

mkdir s01
cp test.txt s01
mkdir s02
cp test.txt s02
mkdir s03
cp test.txt s03
# etc.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.