How to loop command over folders in a directory?

Hello all,

I'm fairly new to scripting so please bear with me. I will try to explain as best as I can but if there's anything that is not clear, please let me know.

I have a directory (see below) with numerous folders and within each of those folders are various files. I would like to run a script that will go into each folder and then select the specified files and then repeat this process for all the folders that are in a given directory. Here is an example of how the path is set up:

The folders contain multiple files with various extensions. I would like the script to go into random#1 folder, look for the specified files, execute the command, and then move onto random#2 folder and do the same.

Inside each folder are the following files:

I have the following script that only works on one specific type of file inside each folder but I need to write a new one that works on specified files (above) located inside each folder in the directory.

How can I make it so that I can replace the above to make a list of all the folders and then run a script that goes inside each folder and looks for the specified files?

Basically, I need the script to go into the directory, into the subdirectory, into the folders, and look for specified files in those folders. And repeat for every folder there is.

I have exhausted all options of self-teaching/experimenting to figure this out on my own and therefore, I'm hoping I can find some solution here.

Thank you in advance.

Let us start with a description of your environment:

  • which OS are you using (and which version of it)
  • which shell are you using (and, maybe, which version of it)

the answers to these questions may well influence the final solution to your problem.

Now, the general solution to your problem is the find -command: basically it produces a list of files, which (see the -exec -clause) then can be subjected to some command. For a (short) introduction see here

I hope this helps.

I am using Ubuntu 12.04 and the shell is the default one that comes with it.

So I have a directory with about 100 folders inside and each of those folders has the following 4 files inside it. I want the script to go into the first folder, look for the files, run the analysis on those files, and then go through the 2nd folder and the 3rd and so on.

I am trying to input those files into this code to automate the analysis instead of having to manually input files using the gui for the program I am using.

Can I just put the script inside the directory with the folder and the text file (with list of folders) and run it from there?

OK. If i am not mistaken Ubuntu uses dash as the default shell, which is (more or less, to be honest i don't know exactly) the same as bash . Perhaps there are some differences, but they are minor.

I understood that already. Now, such a task breaks down to two parts: first, write a script which takes a certain directory name and then executes the task you described below for that one directory (respectively the files in this directory). The second part is to create a list of these directories and then call the script with each of these directory names as arguments.

You probably have overseen my mentioning of the find -command. It has everything you need to do this second part (creating a list of directory names) and i suggest you follow the link i gave you and find out how it works. Once you get that covered we will find out how to write a script which does what you want for one directory supplied on the commandline.

No, it doesn't matter at all where the script resides. It is a good habit to put all your (personal) scripts into one directory - the common name being "bin" and located in your home directory. If there is no such directory i suggest you create it and then modify the file .profile in you home directory to include this line:

PATH="${PATH}:${HOME}/bin" ; export PATH

Now you can put all your scripts into this directory and call them without having to explicitly type the path. (You need to log off and log on again for this to take effect).

I hope this helps.

bakunin

Instead of cd `echo $CASE` you simply do cd "$CASE" .
Instead of "cd" you can use "pushd" and return to the previous directory with "popd".

foreach ...
  pushd "$CASE"
  dtifit ...
  popd
end

You are using csh; instead I recommend to go to bash or ksh. Then, instead of the pushd/popd you can use a ( sub shell ) where the "cd" happens only in the sub shell and the current directory in the main shell is unchanged

#!/bin/bash
for CASE in `cat "DWI_cases_image_path"`
do
  # this is the main shell
  (
     # this is the sub shell
     cd "$CASE" || exit  # on error exit the sub shell
     dtifit ...
  )
  # sub shell ended, we are back in the main shell
done
-rwxr-xr-x 1 root root 929K 2011-05-18 03:00 /bin/bash 
-rwxr-xr-x 1 root root 108K 2011-05-03 08:04 /bin/dash

There is definitively some lack of features in dash which causes bash to use 800 K more in size.

But in the present case here i doubt it will make a any difference at all.

Yes there is a lack of 50k features in dash. On the other hand bash has 750k features too many :smiley:

Perhaps there is some misunderstanding on my part. I'm including screenshots to make sure I did not describe something incorrectly. I went ahead and made a list of all the folders in the directory. Please see below if I have done it correctly.

[quote=madeingermany;302974553]
Instead of cd `echo $CASE` you simply do cd "$CASE" .
Instead of "cd" you can use "pushd" and return to the previous directory with "popd".

foreach ...
  pushd "$CASE"
  dtifit ...
  popd
end

You are using csh; instead I recommend to go to bash or ksh. Then, instead of the pushd/popd you can use a ( sub shell ) where the "cd" happens only in the sub shell and the current directory in the main shell is unchanged

Hmm, pardon my lack of knowledge, but does echo and $ in CASE do the same thing?

Hi,

Try the below code:

for a in `find . -type d`
do
cd $a
yourlogic
cd <lcoation of the script where it is> 
done

This will into all the directories and their sub-directories and apply your logic but you need to come base directory in the script hence i have used cd before the done command.

for a in `find . -type d`
do
for b in filename1 filename2 --> if known else you could use below statement
for b in `ls -l $a| grep ^-| awk '{print $0}'` --> this will check all files in the of variable a.
your logic with $a/$b --> Your file to apply logic
done
done




I am not sure if I understand your question.
Here are some explanations:
$CASE gives the value of the variable CASE .
echo $CASE prints the value of the variable. The value is evaluated before (for example, a * character is a wildcard and eventually replaced by matching files in the current directory). Often you don't want that, then put it in quotes: echo "$CASE" .
Instead of printing it with the echo command, you can cd to it with the cd command.
Now, the cd `echo "$CASE"` is complicated: it first does an echo "$CASE" , but because it is in backticks it does not print to the screen but is passed to the cd command.

I'm sorry to sound so novice but could you explain how I would modify the code to use the filenames that I have in the first post of this thread? Also, I'm confused as to what to put in the 'your logic' part, if you could please explain it further, it would be very helpful.