I have multiple directories and sub-directories like C201201A/RA/, C201202A/RB etc. So I want to copy setphase.sh into all sub-directories and also run it. I have tried the below code

ls -d */*/ > folders.txt
while read folder
    do echo $folder
       cp setphase.sh $folder
       sh setphase.sh
       no=`expr $no + 1`
done < folders.txt

where I have to write sh setphase.sh?

  • 5
    Do you really need to have the script in all of these subdirectories? Or is it sufficient just to be in each directory in turn when the script is run? (This would be far more usual. We don't copy ls into a directory before running it there.) – roaima Aug 4 '16 at 20:46
  • @roaima - yep. if that's the case then something like find . -mindepth 2 -maxdepth 2 -type d -execdir /path/to/setphase.sh {} \; will do the job. – cas Aug 5 '16 at 14:55

If the script doesn't actually need to be in the directory (very few do...and those that do are almost certainly badly written and need to be fixed), you could use find's -execdir option to just run the script inside each directory. For example:

find . -mindepth 2 -maxdepth 2 -type d -execdir /path/to/setphase.sh \;

From the GNU find man page:

-execdir command ;

-execdir command {} +

Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find.

This a much more secure method for invoking commands, as it avoids race conditions during resolution of the paths to the matched files.

As with the -exec action, the + form of -execdir will build a command line to process more than one matched file, but any given invocation of command will only list files that exist in the same subdirectory.

If you use this option, you must ensure that your $PATH environment variable does not reference .; otherwise, an attacker can run any commands they like by leaving an appropriately-named file in a directory in which you will run -execdir.

The same applies to having entries in $PATH which are empty or which are not absolute directory names. If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status. If find encounters an error, this can sometimes cause an immediate exit, so some pending commands may not be run at all.

The result of the action depends on whether the + or the ; variant is being used; -execdir command {} + always returns true, while -execdir command {} ; returns true only if command returns 0.


If all the subdirectory are under C2012A/ directory, you can cp the script to the subdirectories and run it afterwards using a for construct like:

for d in C2012A/*/; do
    cp setphase.sh "$d"
    sh "$d"/setphase.sh

Assuming the script does not depend on the location from where it is being run.

Also note that, by doing sh setphase.sh, you are explicitly mentioning to run the script as an argument to sh (may be dash, bash or other depending on your system) irrespective of the shebang, which may get you undesirable results if you use any bash-isms inside the script.

If the subdirectories are under different directories:

for d in C2012A/*/ A1812A/*/ B8012B/*/; do
    cp setphase.sh "$d"
    sh "$d"/setphase.sh

replace the directory names to meet your requirements.

  • My mistake. Subdirectoriey are present in different directories. – Preet Aug 4 '16 at 20:40
  • @Preet Check my edits.. – heemayl Aug 4 '16 at 20:45
  • Adding this line after copy the script. This works well. ( cd $d && sh setphase.sh ) – Preet Aug 5 '16 at 10:59
  • @Preet the script should work as is in my answer..where is it failing? – heemayl Aug 5 '16 at 12:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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