Shell – How to perform the same set of commands within multiple subdirectories, in a numerical order

forshell-script

Within my parent_directory, I have subdirectories labeled E-11_G, and E-10_G. Within each of those subdirectories, I have more subdirectories labeled E-2_U, E-1_U, and E0_U. In each of those folders, I'm performing commands on these files: ander, ander.band, ander.data, ander.in, and ander.log.

Here's a better picture:

                               parent_directory
                                      ↓
                               E-11_G/ E-10_G/ 
                                  ↓
                          E-2_U/ E-1_U/ E0_U/ 
                            ↓
            ander  ander.band  ander.data  ander.in  ander.log

I want to write a more efficient version of this:

#!/bin/bash

cd parent_directory/E-11_G/E-2_U/; 
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E-1_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E0_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../../E-10_G/E-2_U/;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E-1_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;
cd ../E0_U;
ls -l ander ander.band ander.data;
cat ander.in;
cat ander.log;
pwd;

I've already been able to successfully run this script as is, however, I really need a much more simpler and efficient way of writing it because I'm actually working with a lot more directories than I presented. My reason for doing this is because I need to keep certain records of each of those 'ander' files for each subdirectory. I'm basically planning on running this script and exporting everything that shows up onto the terminal window into a text file using shell > export text as. This is why I want the records for each directory in numerical order.

How can I make my script more efficient? This is the kind of thing I'm aiming for:

#!/bin/bash

cd parent_directory/;

do i= -11, -10 
   do j= -2, 0
      cd  E-i_G/E-j_U/;
      ls -l ander ander.band ander.data;
      cat ander.in;
      cat ander.log;
      pwd;
   end
end

I know that’s pretty much written in Fortran, but is there anything equivalent or similar to this in bash scripting? I've been trying to use 'for loops', but I just can't seem to write them in a way that would give me the same results as my first script.

Best Answer

cd parent_directory/

for i in {-11..-10}
do
   for j in -2 0
   do
      (
      cd  "E${i}_G/E${j}_U/"
      ls -l ander ander.band ander.data
      cat ander.in
      cat ander.log
      pwd
      )
   done
done

Notes:

  • You can loop over a range of numbers by using the braces notation:

    for i in {-11..-10}
    
  • You can also loop over an explicit list of items:

    for j in -2 0
    
  • You can change the directory so some place that depends on variables:

    cd  "E${i}_G/E${j}_U/"
    
  • The argument to the cd command is a directory specified relative to the current directory. After we have done our work in that directory, we want to change back to the parent_directory. There are many ways to deal with this but one simple way is to do that is to put the cd command and commands to be performed in that directory into a subshell, denoted by parens. After we exit the parens, the directory is automatically restored to what it was before.

Related Question