0

I have a shell script app1.sh and a tree of folders, but I don't know how to execute this shell inside each folder. Here is app1.sh script

This script recieves an string, an integer and a file as arguments to work. The idea is to execute it in 4 folders inside a directory.

Thanks all for your help :)

  • can you show us the script? does it support arguments? – BANJOSA Jan 26 at 19:14
  • The title says something about parameters. Could you possibly elaborate on that? – Kusalananda Jan 26 at 23:43
  • Sorry, the correct word is "arguments", not "parameters" my bad. – Daniel Rojas Ariza Jan 27 at 0:36
0

(Ignoring "parameters" in the question title as it's not further explained) Assuming that the app1.sh script is located in the current directory, and that you want to execute this script while inside each and every directory and subdirectory in the current directory:

shopt -s globstar nullglob dotglob

runme=$PWD/app1.sh

for folder in ./**/; do
    ( cd "$folder" && "$runme" )
done

This uses the ** globbing pattern (enabled via the globstar shell option) to find all directories. It then loops over these and uses cd to change directory into each and then executes the script with the directory as its current working directory.

If you only want to process the top-most directories (not their subdirectories), remove globdot and change ./**/ into ./*/.

The nullglob shell option is set to not execute the loop at all if the pattern does not match (there are no directories), and the dotglob shell option is set so that we also match hidden directories.

The parenthesis around the body of the loop encloses the commands in a subshell. The current working directory is local to a subshell, which means we don't have to "cd back out again" after executing the script.


Using find:

runme=$PWD/app1.sh

find . -type d -exec sh -c '
    runme=$1; shift
    for folder do
        ( cd "$folder" && "$runme" )
    done' sh "$runme" {} +

This does the same thing (almost; this will not resolve symbolic links to directories, and it will also find the current directory). For batches of found directories, it calls a short in-line shell script. The script picks out the pathname of the script to run, and then iterates over the remaining arguments (the found directories), changes into the directory, and runs the script.

If you only want to process the top-most directories (not their subdirectories), add the -maxdepth 1 test to the find command:

find . -maxdepth 1 ...as before...

If you don't want to process the current directory, add -mindepth 1 or -name . -prune -o to the command, in a similar way as above. An alternative would be to use find ./*/ ... to use all of the directories in the current directory as search paths, but that would fail with an "argument list too long" error if you have many thousands of directories in the current directory (you would also have to change -maxdepth 1 to -maxdepth 0 if you only want those top-level directories, but I would honestly go with a plain shell loop in that case).

Both -mindepth and -maxdepth are non-standard tests, but are commonly implemented.

Related:

| improve this answer | |
  • Thank you very much for your help, I literally had no idea about doing this. :) – Daniel Rojas Ariza Jan 27 at 0:04
-1

You can use find with -type d for that:

$ PWD=$(pwd); SCRIPT=/full/path/to/script.sh; find . -type d -exec bash -c "cd {}; $SCRIPT; cd $PWD" ";"

With -execdir one can avoid cd $PWD.

$ SCRIPT=/full/path/to/script.sh; find . -type d -execdir bash -c "cd {}; $SCRIPT" ";"
| improve this answer | |
  • And depending what the script does, it might be wise to also use -depth for find. – glenn jackman Jan 26 at 21:37
  • Using -execdir means you don't need all the cd business. – glenn jackman Jan 26 at 21:39
  • What would your script do with a directory called ; rm -rf *? (hint: don't try this, and if you do, make sure you have backups of your home directory available). – Kusalananda Jan 26 at 23:11
  • I don't have directory called rm -rf *... and I'm not going to try. – tansy Jan 26 at 23:21
  • With -execdir you still have to chdir to {}. Just tested it. Also added to answer. – tansy Jan 26 at 23:27

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