1

I'm trying to copy 4 files that are present in Folder A (main folder) into all subfolders (1000) present in Folder A. To do this I used:

for i in *;     
do       
cp  File1.bash $i      
cp  File2.sh $i         
cp  File3.R $i        
cp  File4.R $i       
done  

Unfortunately, the content of all the files after the cp is overwritten in destination directories. In other words files: File2.sh, File3.R and File4.R have the content of File1.bash.

Can anyone help me to solve this problem?

Thank you very much

2 Answers 2

1

The problem here is that the wildcard * is replaced by every file in the directory, including File2.sh,, File3.R and so on. So, at one point during the loop, $i will be 'File2.sh,' and you will execute the command cp File1.bash File2.sh, which will overwrite File2.sh (the same problem happens for the other files).

You should replace the wildcard with a command which only list directory such as ls -d */.

For instance :

for i in $(ls -d */)
do
    cp  File1.bash $i      
    cp  File2.sh $i         
    cp  File3.R $i        
    cp  File4.R $i 
done

Also , note that cp can take multiple arguments as source, so cp File1.bash File2.sh File3.R File4.R $i should do what you want. It is also less error prone as the last parameter is expected to be a directory, so cp will give an error if $i is a regular file.

Sign up to request clarification or add additional context in comments.

1 Comment

You're welcome. Also see my edit about cp taking several arguments and pabouk's answer which contains very useful advice.
1

The for cycle goes through all files and directories (except ones which name starts with a dot) in the current directory including the files File1.bash, File2.s, File3.R, File4.R so sooner or later they will appear in the destination of the cp commands and get overwritten.

There are multiple ways how to resolve the problem:

Expand just directories

for i in */ ; do
    cp  File1.bash File2.sh File3.R File4.R "$i"
done

Test if the destination is a directory

for i in * ; do
    if test -d "$i" ; then
        cp  File1.bash File2.sh File3.R File4.R "$i"
    fi
done

Compared to the first answer this code does not need to call an additional external command (ls) and it is not a good idea to parse output of ls anyway :) (It could contain some unexpected content.)

Move the source files to a different place

For example move the files to directory called .template (the dot is important) or to a directory outside the current directory (../template):

mv File1.bash File2.sh File3.R  File4.R .template

Changed script (will not cycle through the hidden .template):

source=.template
for i in * ; do
    cp  "$source/File1.bash" "$i"
    cp  "$source/File2.sh" "$i"
    cp  "$source/File3.R" "$i"
    cp  "$source/File4.R" "$i"
done

Using double quotes

It is a good idea to enclose string where you expand variables between double quotes. Then the script will correctly work with string containing spaces newlines etc. too.

1 Comment

Haha, originally I forgot the most straightforward solution - the first script :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.