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.