mv *.pdb gas_*.pdb
mv: target 'gas_propane.pdb': Not a directory
Marie-Hélène Burle
Alex Razoumov
By default, scripts get executed linearly from top to bottom. Often however, you will 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 bash.zip
with:
You can then unzip that file with:
You should now have a data-shell
directory with a molecules
subdirectory.
cd
into it:
Sections of scripts can be executed (or not) based on conditions thanks to if statements.
Predicates are expressions that return an exit status of 0 when they are evaluated if they are true and an exit status of 1 if they are 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.
Let’s create a directory and a file:
If we test for the existence of our new directory, we do not get any output nor visible signal:
In fact, we do get a response 0
, which means “yes” or “success”. Since all is good, the shell doesn’t bother us with a signal.
By contrast, if we test for the existence of a non existing file or directory, we get a signal 1
, which means “no” or “failure”:
Your turn:
d1
is a filed1
is a directoryf1
is a filef1
is a directoryIn its simplest form, conditional execution can be limited to failure or success of the previous command.
Commands can be limited to running only if the previous command ran successfully thanks to &&
.
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 both cases, both commands will try to run. Now, if for some reason, the unzipping fails, we have deleted the zip file and we have to re-download it. Not a big deal here, but in some situations, executing a command if the one before fails can be a real bummer.
To prevent this, we can use the double-ampersand (&&
) operator, which plays the role of a logical AND statement:
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 ||
which plays the role of a logical OR statement: the following command only gets executed if the first one fails.
Example:
Sections of scripts can be repeated as long as a condition returns True
thanks to while loops.
The syntax of a while loop in Bash is:
The set of commands in the body of the while loop are executed as long as the predicate returns true.
Be careful that while loop can lead to infinite loops. Such loops need to be manually interrupted (by pressing <Ctrl+C>
).
Example of infinite loop:
Sections of scripts can be repeated for each element of a list thanks to for loops.
The general structure of a for loop is as follows:
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:
Example:
file1
file2
file3
The molecules
directory contains the following .pdb
files:
cubane.pdb ethane.pdb methane.pdb octane.pdb pentane.pdb propane.pdb
We want to rename these files by prepending “gas_” to their current names.
Wildcards don’t work here:
The solution is to use a for loop:
This can also be written as a one-liner, although it is harder to read:
Collections can also be created with brace expansion.
Examples:
Make sure not to add a space after the commas.
ls: cannot access 'ethane.pdb': No such file or directory
ls: cannot access 'methane.pdb': No such file or directory
ls: cannot access 'pentane.pdb': No such file or directory
Brace expansion can be used to create lists iterated over in loops, but also to apply commands to files or directories.
Collections can also be sequences:
Here, 1
is the start of the sequence, 10
is the end, and 2
is the step.
Such a sequence could be used in a loop this way:
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.