var=f1
if [ -e $var ]
then
echo "$var exists"
fi
f1 exists
Marie-Hélène Burle
Alex Razoumov
By default, scripts get executed linearly from top to bottom. Often however, you want to control what gets executed when.
This section covers various ways to control the flow of execution through a script.
For this section, we will play with files created by The Carpentries.
You can download them into a zip file called data.zip
with:
You can then unzip that file with:
You should now have a data
directory.
cd
into it:
Commands get executed from top to bottom and from left to right. Different commands are separated by a line break and/or a semi-colon.
Example:
Look at the following commands:
This is equivalent to:
and to:
This is what we did to get the data for the past few sessions.
In all three cases, both commands will try to run. Now, if for some reason, the unzipping fails, the zip file still gets deleted. That’s a bummer.
Commands can be limited to running only if the previous command ran successfully thanks to the double-ampersand (&&
).
Example:
This is equivalent to:
If the unzipping works (if it returns a zero exit status), then the Zip file gets deleted. If however, the unzipping fails (if it returns a non-zero exit status), the script aborts and we haven’t lost our Zip file.
The opposite of &&
is ||
: the second command only gets executed if the first one failed.
Example:
This can also be written as:
Commands can be executed or not depending on some conditions. To achieve this, we first need to have expressions that define these conditions.
Predicates are expressions that, when evaluated, return either true or false.
Here are examples of predicates:
[ $var == 'text' ]
checks whether var
is equal to 'text'
.
[ $var == number ]
checks whether var
is equal to number
.
[ -e name ]
checks whether name
exists.
[ -d name ]
checks whether name
is a directory.
[ -f name ]
checks whether name
is a file.
Make sure to have spaces around each bracket.
Your turn:
d1
and a file f1
.Write the predicates that test whether:
d1
exists,
d1
is a file,
d1
is a directory,
f1
is a file,
f1
is a directory.
In its simplest form, if
statements look like:
If the condition is true, the commands are executed, if the condition is false, nothing happens.
Your turn:
Write a conditional expression that prints “d1 is a directory” if d1
is a directory and test it.
If you want a different set of commands to be executed when the condition is false, you add an else
statement:
Of course, you can have multiple conditions defining trees of if
statements. In that case, you use elif
(any number of times):
4 is positive
Your turn:
Play with the value of var
to test our if elif else statement.
Commands can be executed as long as a condition returns True
thanks to while loops.
The syntax of a while loop in Bash is:
Be careful that while loops can lead to infinite loops. Such loops need to be manually interrupted (by pressing <Ctrl+C>
).
Example of infinite loop:
Commands can be repeated for each element of a list thanks to for loops.
For loops run a set of commands for each item of a collection. How do you create those collections?
The least efficient method is to list all the items one by one:
Collections can also be created with brace expansion.
Examples:
Make sure not to add a space after the commas.
Collections can also be sequences:
Here, 1
is the start of the sequence, 10
is the end, and 2
is the step.
The general structure of a for loop is as follows:
The molecules
directory contains a number of .pdb
files. We want to rename them by prepending “gas_” to their current names.
We can do this by creating a collection with a wildcard and applying the command to each element of the collection with a for loop:
Here is a for loop using a collection created by a sequence:
Your turn:
In a directory the command ls
returns:
fructose.dat glucose.dat sucrose.dat maltose.txt
What would be the output of the following loop?
All of the text from fructose.dat
, glucose.dat
and sucrose.dat
would be concatenated and saved to a file called sugar.dat
.
The text from sucrose.dat
will be saved to a file called sugar.dat
.
All of the text from fructose.dat
, glucose.dat
, sucrose.dat
, and maltose.txt
would be concatenated and saved to a file called sugar.dat
.
All of the text from fructose.dat
, glucose.dat
and sucrose.dat
will be printed to the screen and saved into a file called sugar.dat
.
Here is a video of a previous version of this workshop.