Bash

From UC_Chemistry

Jump to: navigation, search

A Bash tutorial for computational chemists. Common recipes for setting up login shells on clusters will constitute another document.

Contents

Introduction

I came to know bash by way of old manuals for UNIX dating from the time of the Bourn Again Shell's predecessor, sh. Since then, I have added to my knowledge with the help of the manpage and several other good (and usually sparse) references when I needed to get something done. Since I suspect that most people like myself can only learn one thing at a time, while they are in the business of trying to get it done, I am collecting useful recipes on this page in the hope that it can serve as a reference and a learning tool.

This document will thus follow some loose overall structure going from high to low-use bash syntaxes and then high to low-use utilities commonly used to get things done in the shell world. Each entry should contain a couple of examples for the impatient followed by some explanation of what the above has just done to your system if you ran it before reading further and then some comments on how to play around with the syntax so that we can learn by experimentation.

Syntax

Shell / Environment Variables

Setting and displaying:

a=value
echo $a
export a

Conditional Execution

Ands and or-s:

mkdir /root/cant_do_it || echo "Could not create directory."
echo a && echo b || echo c
grep -q "alias" ~/.bashrc || ! echo "No aliases." && echo "Aliases found"

The above show how to use simple one-line logical ands, ors, and nots to make statements that execute intelligently. Most commands return true on success and false on failure. A conceptual caveat is that the actual return value for success is zero, and failure is nonzero. For those of you who know any programming language, this is counter-intuitive (opposite to convention), so it is better to think of return values in terms of success = true, faulure = false. A good way to experiment with the above is by replacing the commands with others of your own choosing, possibly including parentheses. The last example gives a nice way to find out if a file contains the word "alias" in it. Grep -q doesn't print out matching lines, but returns true if it found the pattern. Echo always returns true, so its value has to be negated so that only one of the last two statements will execute. This example is not yet idiot-proof, since the file ~/.bashrc may not exist.

if [ "xa" = "xb" ]; then
    echo "true"
else
    echo "false"
fi

for example

#!/bin/bash 
COUNTER=0
while [  $COUNTER -lt 10 ]; do
 echo The counter is $COUNTER
 let COUNTER=COUNTER+1 
done

This is the standard if-then-else clause. You can leave out else if you want. If-then clauses must always be terminaref by fi (if backwards).

var="-k"
case "$var" in
    "-k")
        echo "Kicking molecule..."
        ~/bin/kick $molecule
        ;;
    "-a")
        echo "Adding molecule to output."
        cat $molecule >>$output
        ;;
    "-f")
        echo "Finished program."
        exit 1
        ;;
    *)
        echo "Unrecognized option: $var"
        ;;
esac

These switch statements are very useful for interpreting command line options inside shell scripts, where they are usually preceded by a call to getopt to parse the options and/or combined with "while [ $# -gt 0 ]" and shift to loop through all arguments. Note that each matching clause contains a list of commands to be executed by the shell and must be terminated with two adjacent semicolons (except for the last clause) and that the whole section is terminated by case spelled backwards.

Streams / Pipes

a | b
a | b | c | ...

Loops

For Loops

for i in *; do
echo $i
[ -r $i.test ] && echo "Found $i.test"
done

Utilities

Directory Operations

"ls" the following will list the directory size and the size of each file in human readable format.

$ ls -lh 

"test" or "[]" the following example will output "readable" if myfile1 is readable

$ if [ -r myfile1 ];then echo readable; fi

This uses find to locate all files below the current directory "." with size less than 10kB:

find . -size -10k

File Operations

Note that most command line tools can accept input from a file or stdin.

$ cat filename
$ cat filename | head

Print the contents of the file to stdout. The pipeline connects the stdout of any previous program to the stdin of the next.

$ head -20 filename

Print the first 20 lines of a file.

$ tail -10 filename

Print the last 10 lines of a file.

$ more filename
$ less filename

Read the file in your terminal window.

$ sed -e '--sed script here--' infile >outfile

Run sed on the input file and send the output to a new file. For script details, see the Sed page.

$ cat filename | tr "[:upper:]" "[:lower:]" 

Translate characters appearing in set 1 (upper) to those in set 2 (lower). tr only accepts input from stdin...

String Operations

echo

Useful options: -n You can use any of the file operations above with echo if they also accept input from stdin, as in echo "string" | ... .

basename /home/user/test.var .var

dirname

References

Personal tools