0

I have a script called summarize.sh which produces a summary of the file/dirs inside of a directory. I would like to have it run recursively down the whole tree from the top. Whats a good way to do this?

I have tried to loop it with a for loop with

for dir in */; do
cd $dir
./summarize.sh
cd ..

however it returns ./summarize.sh: no file or directory Is it because I am not moving the script as I run it? I am not very familiar with unix directories.

gt6989b
  • 4,125
  • 8
  • 46
  • 64
llssff
  • 119
  • 7
  • [How to go to each directory and execute a command?](https://stackoverflow.com/q/7470165/608639), [Perform an action in every sub-directory using Bash](https://stackoverflow.com/q/4000613/608639), [How to enter all subdirectories and execute command on files inside?](https://stackoverflow.com/q/42931420/608639), [Run a script from every directory on ubuntu linux](https://askubuntu.com/q/1115420), etc. – jww May 01 '19 at 04:34
  • In each case where you want to do something on the contents of each directory beginning at some point in the filesystem, you will normally use `find /path/start -type d -exec someutility '{}' \;` where each directory is passed to the script `someutility` for further processing. – David C. Rankin May 01 '19 at 07:00

3 Answers3

1

You can recursively list files using find . -type f and make your script take the interested file as a first argument, so you can do find . -type f -exec myScript.sh {} \;

If you want directories only, use find . -type d instead, or if you want both use just find . without restriction.

Additional option by name, e.g. find . -name '*.py'

Finally, if you do not want to recurse down the directory structure, i.e. only summarize the top level, you can use -maxdepth 1 option, so something like find . -type d -maxdepth 1 -exec myScript.sh {} \;.

gt6989b
  • 4,125
  • 8
  • 46
  • 64
1

The issue is that you are changing to a different directory with the cd command while your summarize.sh script is not located in these directories. One possible solution is to use an absolute path instead of a relative one. For example, change:

./summarize.sh

to something like:

/path/to/file/summarize.sh

Alternatively, under the given example code, you can also use a relative path pointing to the previous directory like this:

../summarize.sh
Jason K Lai
  • 1,500
  • 5
  • 15
0

Try this code if you are running Bash 4.0 or later:

#! /bin/bash -p

shopt -s nullglob   # Globs expand to nothing when they match nothing
shopt -s globstar   # Enable ** to expand over the directory hierarchy

summarizer_path=$PWD/summarize.sh

for dir in **/ ; do
    cd -- "$dir"
    "$summarizer_path"
    cd - >/dev/null
done
  • shopt -s nullglob avoids an error in case there are no directories under the current one.
  • The summarizer_path variable is set to an absolute path for the summarize.sh program. That is necessary to allow it to be run in directories other than the current one. (./summarize.sh only works in the current directory, ..)
  • Use cd -- ... to avoid problems if any directory name begins with '-'.
  • cd - >/dev/null to cd to the previous directory, and throw away its path when it is output by cd -.
  • Shellcheck issues several warnings about the code above, all to do with the use of cd. I'd fix them for "real" code.
pjh
  • 6,388
  • 2
  • 16
  • 17
  • It returns an error ```/summarize.sh: No such file or directory``` for every directory it tried to run in – llssff May 01 '19 at 21:49
  • @llssff, check for typing errors on the `summarizer_path=$PWD/summarize.sh` line. The [PWD](https://www.gnu.org/software/bash/manual/bash.html#index-PWD) built-in variable in Bash always contains the absolute path of the current directory. It should never be undefined or empty. – pjh May 02 '19 at 09:36