Shell Script to Execute Shell Script to All Subdirectories

7,628

Solution 1

find will save you:

find /your/dir/with/subdirs -type d -exec sh -c 'cd "{}" ; /path/to/your/script.sh ;' \;

Solution 2

There are several problems in your script.

cd $MainDir

Better make this cd "$MainDir". Here this is not important, but it's a good habit to get into. If you leave a variable expansion unquoted, the value of the variable is split into words, and each word is treated as a shell wildcard pattern; so this command would fail if $MainDir contained whitespace or \[?*. Putting double quotes never hurts (unless you want splitting and filename matching to happen), and avoids these extra expansions. The same goes for command substitutions ($(somecommand)). Always put double quotes around variable and command substitutions unless you know you want splitting and filename matching.

for dir in $(ls); do

Don't parse the output of ls. You almost never need ls in scripts. As explained above, the result of a command substitution is split into words that are treated as wildcard patterns, so $(ls) mangles whitespace and wildcard characters, in addition to the mangling of non-printable characters that ls may do. Listing the file names in a directory is built into the shell:

for dir in *; do

If you make that for dir in */; do, only subdirectories of the current directory are matched, not other kinds of files.

if [ -f $dir/sysconfig.out];

You need whitespace on each side of the brackets, except when the character next to it is a shell punctuation character: ();&|<>. And again, put double quotes around the variable substitutions (this goes for every other place where you have a variable substitution): if [ -f "$dir/sysconfig.out" ];

#cd back to where we started
cd $OLDPWD

This is useless: the process is about to exit, changing its current directory won't affect anything. Note that each process has its own current directory: changing it in a script does not affect the program that called the script.


Turning to the reason you asked this question, it isn't clear what you want. “binary file /some/subdirectory/” doesn't make much sense: you wouldn't get this message with a directory. For better help, copy-paste the error message. You should always copy-paste error messages when you ask for help online.

From your description, it seems that files have moved one directory level deeper. If that's the case, change the line for dir in */; do to

for dir in */*/; do

Solution 3

There are numerous ways you could do this. you could either run your existing script in a for loop, or use find and xargs, or perhaps even make use of grep's -r aka --recursive option.

The simplest is probably just to write a for loop wrapper around your existing script. For example:

#! /bin/bash
cd /path/to/top/level/directory

for d in */ ; do 
  pushd $d
  # call your script here
  popd
done
Share:
7,628

Related videos on Youtube

JudeJitsu
Author by

JudeJitsu

programming noob. self studying.

Updated on September 18, 2022

Comments

  • JudeJitsu
    JudeJitsu over 1 year

    I am making a script to simplify my daily tasks. Everyday, I have to grep for a few things inside a company server. It was okay, however, now, they have segregated each object into sub directories. I am looking for a solution in which my existing shell script will execute repeatedly into each sub directory inside a certain directory. How do I do this? I am quite new to Linux and still learning the ropes.

    Here's my script:

    #!/bin/bash
    MainDir=/path/to/dir/containing/subdirs
    # cd into dir
    cd $MainDir
    
    for dir in $(ls); do
    
    #fetch start time of uut
    grep -i "01_node_setup" $dir/his_file | tail -1 >> /home/xtee/sst-logs.out
    
    #check if sysconfig.out exists
    if [ -f $dir/sysconfig.out];
    then
        grep -A 1 "Drive Model" $dir/sysconfig.out | tail -1 >> /home/xtee/sst-logs.out
    else
        grep -m 1 "Pair0 DIMM0" $dir/node0/trans_file_prev/*setupsys* | tail -1 >> /home/xtee/sst-logs.out
    fi
    
    done
    
    #cd back to where we started
    cd $OLDPWD
    

    A nice guy helped me with the script, and the script above is what came out. It worked alright however, the sst-logs.out file displays binary file /some/subdirectory/ instead of the output of the grep. What is wrong in the script?

    • Marco
      Marco almost 12 years
      Does the grep switch -R for recursive help?
    • JudeJitsu
      JudeJitsu almost 12 years
      @Marco, it might if the subdirectories contain only one each file name i am grepping to which is not the case. the subdirectories also have their own subdirectories which has the file with the same file name (e.g. history) which i do not want...
  • JudeJitsu
    JudeJitsu almost 12 years
    Thanks Craig. Will try this... Appreciate the help :) Can this be done to CD just one sub directory deep? Because the subdirectories have their own "history" subdirectory which contains the same file name.
  • JudeJitsu
    JudeJitsu almost 12 years
    Thanks rush... Will also try this. I am looking for the lightest implementation.. :)
  • Alessio
    Alessio almost 12 years
    as written, it only iterates through the first-level subdirectories of your top-level directory. i.e. yes. if you needed it to process every subdirectory below that you'd have to do something like for d in $(find . -type d); do ...