Bash Programming Interactive lecture#
We recommend using your own choice of text editor#
* Everyone should know how to exit and edit text in vimVim basics#
On some supercomputers (e.g. SAGA), vim may be the only option for text editing.
Open vim and a textfile hello_world.sh with $ vim hello_world.sh
To edit text in vim we have to enter INSERT mode by typing “i”
The cursor can not be moved with mouse clicks. Use arrows and “PgUp”, “End” etc.
Inside INSERT mode text can be edited as normal
To exit INSERT mode press Esc
To save changes type :w
To exit vim (important!), type :q
Save and exit :wq
Reminder: Combining bash commands: Pipes#
The bash pipe |
connects STDOUT
of one command to STDIN
of another.
Live programming: Oslo’s weather report.#
⚠️ Unix commands used here:
curl: downloads a website
grep: filter lines with a given keyword
head: limit the output to the first X lines
cut: select a specific column defined by a deliminter
cowsay: let a cow say something
Interactive programming#
Solve the following exercises:
Implement a weather forcast script that outputs the current weather in Bergen (i suggest using https://pent.no or https://wttr.in/your_location). Feel free to vary the layout and amount of details in the output.
(Optional) Implement a script that outputs headlines of nrk.no.
(Optional) Implement a weather forecast script as in 1) using www.yr.no.
useful: curl, grep, head, cut, (cowsay)
Time: 15 minutes
More pipe examples#
Sort all files in a directory tree, with the largest files appearing first, and equip the output with paging functionality:
du -a lectures | sort -rn | less
⚠️ du shows the disk usages of files
⚠️ sorts sorts the input
⚠️ less paginates the output for easier reading
Save output to disk and display it on the console:
./weather.sh | tee weather.log
⚠️ tee writes STDIN
to STDOUT
and file
Quiz: Can you simplify this code?#
ls > files.txt ; grep weather < files.txt ; rm files.txt
⚠️ CMD1 ; CMD2 executes CMD2
after CMD1
.
The code above implements an (inefficient) pipe.
Better:
ls | grep weather
Functions#
Bash has simple support for functions.
function geturl {
# function arguments: $1 $2 $3 and so on
if [ $1 == "Oslo" ]; then
url="https://www.yr.no/place/Norway/Oslo/Oslo/Oslo/"
fi
}
# call:
geturl "Oslo"
echo $url # Bash functions have no return values, but all variables are global
Interactive programming#
Implement a “geturl” function that takes a city as input and stores the assoicated weather report url as output.
The function should work for Bergen, Oslo and Stavanger.
If an invalid city is provided, the function should exit the script and print an error message.
Optional: Print out the current weather instead of the link to the website
Time: 10 minutes
Convenient debugging tool: -x#
Each source code line is printed prior to its execution if you add -x as option to /bin/sh
or /bin/bash
Either in the header
#!/bin/bash -x
or on the command line:
bash -x scripts/weather_functions.sh
Live example
!scripts/weather_functions.sh
Reminder: command line arguments#
Bash provides the special (array) variable $
for accessing these arguments:
$0
contains the script name$1
contains the first command line option$2
contains the second command line option…
Interactive programming#
Extend your weather forecast script so that it takes the city as a command line option:
Example usage:
weather.sh Oslo # Prints out Oslo's weather
weather.sh Mars # Prints out an error message (not a city)
(Optional): Print a short usage documentation for the script when no command line options are provided.
Time: 10 minutes
Running an application in the foreground#
Syntax:
cmd &
executes a program in the background.Use
wait
to block a script until all background processes are completed.
Example:
myprog -c file.1 -p -f -q < my_input_file &
# any commands here will be executed while myprog is still running
Live demo:
scripts/background_test.sh
File globbing, for loop on the command line#
List all .ps and .gif files using wildcard notation:
files=$(ls *.png *.eps)
# compress and move the files:
gzip $files
for file in $files; do
cp ${file}.gz $HOME/Pictures
done
⚠️ gzip compresses a file, cp copies a file, $HOME is a string with the path to your home directory.
The find command#
Very useful command!
⚠️ find
visits all files in a directory tree and can execute one or more commands for every file
Basic example: find the weather
codes
find -name 'weather*'
Or find all log and PDF files
find $HOME -name '*.log' -o -name '*.pdf'
That is it for today#
Applications of find (1)#
Find all files larger than 2000 blocks a 512 bytes (=1Mb):
find $HOME -name '*' -type f -size +2000 -exec ls -s {} \;
Remove all these files:
find $HOME -name '*' -type f -size +2000 \
-exec ls -s {} \; -exec rm -f {} \;
or ask the user for permission to remove:
find $HOME -name '*' -type f -size +2000 \
-exec ls -s {} \; -ok rm -f {} \;
Backup slides#
Redirects and pipes can be combined#
View STDOUT
and STDERR
with paging functionality:
./compile 2>&1 | tee compile.log | less
Example: bundle files#
Pack a series of files into one file
Executing this single file as a Bash script packs out all the individual files again
Usage:
bundle file1 file2 file3 > onefile # pack
bash onefile # unpack
Writing bundle
is easy:
#/bin/sh
for i in $@; do
echo "echo unpacking file $i"
echo "cat > $i <<EOF"
cat $i
echo "EOF"
done
The bundle output file#
Consider 2 fake files: file1
:
Hello, World!
No sine computations today
and file2
:
1.0 2.0 4.0
0.1 0.2 0.4
Running bundle file1 file2
yields the output
echo unpacking file file1
cat > file1 <<EOF
Hello, World!
No sine computations today
EOF
echo unpacking file file2
cat > file2 <<EOF
1.0 2.0 4.0
0.1 0.2 0.4
EOF
Note: In the terminal, you can send a foreground job into the background by pressing Ctrl-Z
followed by the bg
command, and retrieve it again with fg
.
How to return a value from a function? Define a new variable within the function - all functions are global!
Applications of find (2)#
Find all files not being accessed for the last 90 days:
find $HOME -name '*' -atime +90 -print
and move these to /tmp/trash:
find $HOME -name '*' -atime +90 -print \
-exec mv -f {} /tmp/trash \;
Tar and gzip#
⚠️ The tar
command can pack single files or all files in a directory tree into one file, which can be unpacked later
tar -cvf myfiles.tar mytree file1 file2
# options:
# c: pack, v: list name of files, f: pack into file
# unpack the mytree tree and the files file1 and file2:
tar -xvf myfiles.tar
# options:
# x: extract (unpack)
The tarfile can be compressed:
gzip mytar.tar
# result: mytar.tar.gz
A find/tar/gzip example#
Pack all PostScript figures:
tar -cvf ps.tar `find $HOME -name '*.ps' -print`
gzip ps.tar