NewUsr_stat
NewUsr_stat

Reputation: 2583

Files overwritten during cp loop

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

Upvotes: 1

Views: 123

Answers (2)

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.

Upvotes: 1

archz
archz

Reputation: 1072

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.

Upvotes: 1

Related Questions