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 :)

2 Answers2

1

(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:

Kusalananda
  • 333,661
-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" ";"
tansy
  • 741