Bash For Loops (Plus a Little Scripting)

I’ve written about Bash scripting previously, as it applies to neuroimaging. Scripting is extremely useful; it can save hours worth of work. But what if you want to do something that is repetitive but do not really need to create a script? This is where the for loop is useful.

First I will start with a more complicated example before I get to the for loop. This one requires a little bash scripting. You have a problem, you want to create 400 subject directories (don’t ask me why, I’m just providing an example) but don’t want to create them one by one. A simple script could save a lot of time:

#!/bin/sh

t=0 #this specifies a starting value

read -p “How many subject directories would you like to create? ” SUBS ;

let SUBS1=${SUBS}+1 #creates a new variable (SUBS1) that is one value greater than the input

condition ()

{

((t++))

if [ $t -lt ${SUBS1} ]

then

return 0  # true

else

return 1  # false

fi

}

read -p “Enter the full path (no trailing /) to the directory where you would like to create the directories: ” SUBSDIR

while condition

#     ^^^^^^^^^

#     Function call — ${SUBS1} loop iterations.

do

mkdir ${SUBSDIR}/sub${t} ; #The “sub” could be changed to whatever you want the prefix to be (e.g., blind, subject, con, exp).

done

This script was modified from one on this site (about bash loops) with input from this site (about bash mathematics). I created that script even though you (or I) probably will not use it very much or at all; it is useful for showing a quick way to create a lot of consecutively numbered directories somewhere on your computer. This script also can be modified as needed in order to do similar functions. I actually only wrote the script so I would have a list of directories to use for this example. Here is the result of the script:

Now I will move on to the real purpose of this post: not scripting but for loops.

Let’s say that you want to create a labels directory within a series of subjects’ FreeSurfer directories (or anywhere else). We can pretend that those subjects directories I created above are my FreeSurfer subjects. For this we do not need to write a whole script; a simple for loop will suffice.

First cd to your FreeSurfer subjects directory – e.g., cd /Applications/freesurfer/subjects

Then create a text file with the list of subject directories you want to deal with: ls >> blinds.txt

Next, open that file to remove any unwanted items: open -a TextEdit blinds.txt

After it only contains a list of the subjects you are ready to save it, close it, and proceed.

Now we are ready to use a for loop to create a bunch of directories called labels (one within each FreeSurfer subjects directory):

for blind in `cat blinds.txt`; do mkdir /Applications/freesurfer/subjects/${blind}/labels; done

That’s it. Pretty simple! A for loop requires a for, a do, and a done. The semi-colons ( ; ) are required when running a multi-step command like this on a single line.

Here is a screenshot of what my subjects directory (pretend this is my FreeSurfer subjects directory) now looks like:

Also notice the blinds.txt file that I created by listing the subjects directory and saving that output to a text file (which I then edited).

That is one example of a simple for loop. Any repetitive task that we can use bash for can be put in a simple loop like that. Here is another example using a FreeSurfer command (all the dashes are double dashes): for blind in `cat blinds.txt`; do mri_annotation2label --subject ${blind} --hemi lh --outdir labels; done

Or, you could copy a number of files from one location to another: for blind in `cat blinds.txt` ; do mkdir /my_new_imaging_directory/${blind} ; cp ./${blind}/${blind}_T1.nii.gz /my_new_imaging_directory/${blind}/${blind}_T1.nii.gz ; done

That loop is slightly more complicated, it has a couple commands in the do part. First, I make a series of new target directories (you wouldn’t need to include that if the target directories exist already): mkdir… ; then, I copy images from one location to another: cp …. A command like this is useful in a script if you want to create temporary files to process further and then remove. I like to create copies of files so I do not accidentally and permanently alter the original images. Just make sure you remove the temp files when you are done or you will end up with a lot of redundant files.

Looping is one reason why it is important to be consistent in labeling files and directories. Name directories that make sense; keep all your images and files organized. If you are consistent, you can throw a simple for loop together and save a lot of time without having to write a script. I use loops at least weekly but I create or use scripts less often.

About Jared Tanner

I have a PhD in Clinical and Health Psychology with an emphasis in neuropsychology at the University of Florida. I previously studied at Brigham Young University. I am currently a Research Assistant Professor at the University of Florida. I spend the bulk of my research time dealing with structural magnetic resonance images of the brain. My specialty is with traditional structural MR images, such as T1-weighted and T2-weighted images, as well as diffusion weighted images. I also look at the cognitive and behavioral functioning of individuals with PD and older adults undergoing orthopedic surgery. Funding for the images came from NINDS K23NS060660 (awarded to Catherine Price, University of Florida). Brain images may not be used without my written permission (grant and software requirements).