0

Let's say I have 10 subdirectories in a main-directory named d1, d2, d3, ..., d10. How can I copy a file into all these subdirectories using cp?

I'm looking for something like

cp ./my_file.txt ./d*/
brownser
  • 161

2 Answers2

2

It doesn't work this way, for multiple reasons: Firstly, cp only accepts one single destination argument. For example, if you execute the following command

cp file1.txt file2.txt something_else.txt my_destination/

from the list of arguments to cp, file1.txt dir7/ file2.txt my_destination/, only the very last one will be interpreted as the destination where to copy the others to.

Secondly, wildcards get handled differently in Bash than you seem to think. Bash does a lot of so called expansions beforehand, before the command in question even gets called. One of those expansions concerns the * wildcard.

Let's say you have the directories d1, d2 and d3. In this case, Bash would expand d* to d1 d2 d3. So the following

cp my_file.txt d*

would become

cp my_file.txt d1 d2 d3

all before cp even gets called. And this would mean something like "copy myfile.txt, d1 and d2 to d3". Remember, only the very last parameter gets interpreted as the destination.

What you can do is a simple for loop over the directories. To give you the general idea:

for DIR in d*; do
  cp my_file.txt "$DIR"
done

In case you also have files that would match d*, in addition to the directories, things would get a bit more involved. But that would be a seperate question ;)

  • Hi, thanks for the detailed explanation. There seems to be a small syntax error in the bash script you provided. I have tried to edit it, Can you please fix that so that I can accept the answer? – brownser Jan 20 '23 at 10:29
  • 1
    @brownfox Somebody else already reviewed the answer, so that's taken care of. The semicolon in this place actually isn't obligatory, see for example this question over at Unix.SE. But I agree that the version with the semicolon is probably more common. – Henning Kockerbeck Jan 20 '23 at 12:17
1

You can do this with xargs command.

echo ./d* | xargs -n 1 cp -v ./my_ file.txt

man xargs