Skip to content

05 loops_notes

Carsten Fortmann-Grote edited this page Mar 15, 2024 · 1 revision

Loops

Questions

  • How can I perform the same actions on many different files?

Objectives

  • Write a loop that applies one or more commands separately to each file in a set of files.
  • Trace the values taken on by a loop variable during execution of the loop.
  • Explain the difference between a variable’s name and its value.
  • Explain why spaces and some punctuation characters shouldn’t be used in file names.
  • Demonstrate how to see what commands have recently been executed.
  • Re-run recently executed commands without retyping them.

What’s a loop

file:img/2024-03-15_11-02-32_010fce9abaa5dfea2cabb7ce9cdcb255--ay-physics.jpg

file:img/2024-03-15_11-08-25_264548_Corkscrew_(Cedar_Point)_01.jpg

  • entry
    • core / body
  • exit
  • A loop performs repetitive tasks without having to rewrite the command again and again.

Different kinds of loops

  • for loop: Do core N times / iterate list
  • while loop: If condition holds, do core
  • do-while loop: do core, repeat if condition holds

Example: print first 5 lines of multiple files

In shell-lesson-data/exercise-data/creatures/:

$ head -n basilisk.dat minotaur.dat unicorn.dat

Take the 2nd line from each file (use a pipe)

$ head -n 2 basilisk.dat | tail -n 1
$ head -n 2 minotaur.dat | tail -n 1
$ head -n 2 unicorn.dat  | tail -n 1

Now use a for loop

$ for creature in basilisk.dat minotaur.dat unicorn.dat
  do
      head -n 2 $creature | tail -n1
  done

General structure of a for loop

# The word "for" indicates the start of a "For-loop" command
# "thing" is the loop variable (it changes its value in each iteration)
for thing in list_of_things
#The word "do" indicates the start of job execution list
do
    # Indentation within the loop is not required, but aids legibility
    # The value of variable "thing" is referenced by the "$" character
    operation_using/command $thing
# The word "done" indicates the end of a loop
done

Note

  • prompt changes from “$” to “>” to indicate that input is expected.
  • Exit entry by holding |CTRL| and |C| at the same time (|ctrl-c|).

Your first loop

Exercise

Task

  • Write a for loop that prints out (echo) the numbers 0-9

Solution

Variables in loops

Exercise

Task

This exercise refers to the shell-lesson-data/exercise-data/alkanes directory.

$ ls *.pdb

cubane.pdb  ethane.pdb  methane.pdb  octane.pdb  pentane.pdb  propane.pdb

What is the output of the following code?

$ for datafile in *.pdb
> do
>     ls *.pdb
> done

Now, what is the output of the following code?

$ for datafile in *.pdb
> do
>     ls $datafile
> done

Why do these two loops give different outputs?

Solution

Limiting Sets of Files

Exercise

Task

What would be the output of running the following loop in the shell-lesson-data/exercise-data/alkanes directory?

$ for filename in c*
> do
>     ls $filename
> done
  1. No files are listed.
  2. All files are listed.
  3. Only cubane.pdb, octane.pdb and pentane.pdb are listed.
  4. Only cubane.pdb is listed.

Solution

Limiting Sets of Files (continued)

How would the output differ from using this command instead?

$ for filename in *c*
> do
>     ls $filename
> done
  1. The same files would be listed.
  2. All the files are listed this time.
  3. No files are listed this time.
  4. The files cubane.pdb and octane.pdb will be listed.
  5. Only the file octane.pdb will be listed.

Saving to a File in a Loop - Part One

Exercise

Task

In the shell-lesson-data/exercise-data/alkanes/ directory, what is the effect of this loop?

for alkanes in *.pdb
do
    echo $alkanes
    cat $alkanes > alkanes.pdb
done
  1. Prints cubane.pdb, ethane.pdb, methane.pdb, octane.pdb, pentane.pdb and propane.pdb, and the text from propane.pdb will be saved to a file called alkanes.pdb.
  2. Prints cubane.pdb, ethane.pdb, and methane.pdb, and the text from all three files would be concatenated and saved to a file called alkanes.pdb.
  3. Prints cubane.pdb, ethane.pdb, methane.pdb, octane.pdb, and pentane.pdb, and the text from propane.pdb will be saved to a file called alkanes.pdb.
  4. None of the above.

Saving to a File in a Loop - Part Two

Also in the shell-lesson-data/exercise-data/alkanes/ directory, what would be the output of the following loop?

for datafile in *.pdb
do
    cat $datafile >> all.pdb
done
  1. All of the text from cubane.pdb, ethane.pdb, methane.pdb, octane.pdb, and pentane.pdb would be concatenated and saved to a file called all.pdb.
  2. The text from ethane.pdb will be saved to a file called all.pdb.
  3. All of the text from cubane.pdb, ethane.pdb, methane.pdb, octane.pdb, pentane.pdb and propane.pdb would be concatenated and saved to a file called all.pdb.
  4. All of the text from cubane.pdb, ethane.pdb, methane.pdb, octane.pdb, pentane.pdb and propane.pdb would be printed to the screen and saved to a file called all.pdb.

Doing a dry run

A loop is a way to do many things at once — or to make many mistakes at once if it does the wrong thing. One way to check what a loop would do is to echo the commands it would run instead of actually running them.

Suppose we want to preview the commands the following loop will execute without actually running those commands:

$ for datafile in *.pdb
> do
>     cat $datafile >> all.pdb
> done

Exercise

Task

What is the difference between the two loops below, and which one would we want to run?

Version 1

$ for datafile in *.pdb
> do
>     echo cat $datafile >> all.pdb
> done

Version 2

$ for datafile in *.pdb
> do
>     echo "cat $datafile >> all.pdb"
> done

Solution

Nested loops

Exercise

Task

Suppose we want to set up a directory structure to organize some experiments measuring reaction rate constants with different compounds and different temperatures. What would be the result of the following code:

$ for species in cubane ethane methane
> do
>     for temperature in 25 30 37 40
>     do
>         mkdir $species-$temperature
>     done
> done

Solution

Take home

  • A for loop repeats commands once for every thing in a list.
  • Every for loop needs a variable to refer to the thing it is currently operating on.
  • Use $name to expand a variable (i.e., get its value). ${name} can also be used.
  • Do not use spaces, quotes, or wildcard characters such as ‘*’ or ‘?’ in filenames, as it complicates variable expansion.
  • Give files consistent names that are easy to match with wildcard patterns to make it easy to select them for looping.
  • Use the up-arrow key to scroll up through previous commands to edit and repeat them.
  • Use |Ctrl+R| to search through the previously entered commands.
  • Use history to display recent commands, and ![number] to repeat a command by number.