Shell

Bash

Bourne Again SHell, is also a language

  • How to run a bash script:
    • bash /path/to/script
    • chmod +x /path/to/script then /path/to/script (requires shebang)

Script

Comments

  • Comments: Starts with ”#”
  • Shebang: A special comment that specifies that the file is a script and calls a certain interpreter, e.g. bash, python.
    • #!/bin/bash
    • #!/usr/bin/python

Variable

NAME="value"
echo "$NAME"
  • Whitespace matters!
  • Use $VAR, or ${VAR} (preferred) to output the value of the variable VAR
  • Variable in bash is untyped
  • Operations are contextual
  • Everything is string

Use expr command or $(()) (better way) to evaluate expressions.

FOO=1
expr $FOO + 1 		# 2
expr $FOO+1   		# 1+1
echo $((FOO + 1))   # 2
echo $((FOO+1))     # 2

Use the read command to get user input, -p is for optional prompt (Not supported by zsh, use echo -n instead)

read -p "send: " FOO
echo "send: $FOO"

Subshell: Use $() evaluate the command inside it and substitute the output into the script.

BAR=$(ls)
echo "$BAR"

Condition

test, synonymous with [], could evaluate an expression and set exit status ($?) to:

  • 1 (false)
  • 0 (true)

Comparison:

  • -eq: ==
  • -ne: !=
  • -gt: >
  • -lt: <
  • -ge: >=
  • -le: <=
a=10
b=2
 
[ "$a" -le "$b" ]    	# false
[[ "$a" <= "$b" ]]  	# true (String)
(( a <= b ))        	# false

Note

  • [ ... ]: A command: POSIX test, the oldest one.
  • [[ ... ]]: Modern shell condition keyword.
  • (( ... )): Expression evaluation, $? will be set as 0 (true) if outcome is not 0

Boolean operations:

  • && and || for shell
  • -a (and) and -o (or) for test ([])
false || echo "Oops, fail"
# Oops, fail
 
true || echo "Will not be printed"
#
 
true && echo "Things went well"
# Things went well
 
false && echo "Will not be printed"
#
 
true ; echo "This will always run"
# This will always run
 
false ; echo "This will always run"
# This will always run

(false is a command always returning 1 and true is a command always return 0)

[ 0 -le 1 ] && [ 0 -gt 1 ]; echo $?
# 1
[ 0 -le 1 -o  0 -gt 1 ]; echo $?
# 0 

if statement:

if [ $1 -lt 0 ]; then
  echo "$1 is less than 0"
elif [ $1 -eq 0 ]; then
  echo "$1 is equal to 0"
else
  echo "$1 is greater than 0"
fi

case statement: Use to pattern match

case $1 in
  Mon|Tue|Wed|Thu|Fri)
    echo "Weekday..."
    ;;
  Sat|Sun)
    echo "Weekend!!!"
    ;;
  *)
    echo "Invaild"
esac

Loop

Array: my_array=(apple banana cherry)

for loop:

SHEEP=("one" "dos" "tre")
for S in $SHEEP; do
  echo "$S sheep..."
done

In fact, for can also traverse a string with $IFS as delimiter.

  • With index:
n=0
for x in {1..10}; do
  n=$(($x + $n))
done
echo $n

while loop:

while true; do
  echo "yes"
done

Function

function greet() { # () is optional.
  echo "Hello, $1!"
}
greet "World"

Functions has its own environment but a subtle difference: $1 in function will be the argument passed in the function, not the global one (the argument passed in the script), even if function is called without argument.

  • function is a keyword not supported by POSIX which could return an integer and use $FUNCNAME access function’s name, but without function keyword, () is required.
  • local can declare a variable in the field of function.

Stream

  • >: Output to somewhere else, like a text file. (If there’s anything in the file before, it will be overwritten!)
    • echo "Hello, Wolrd!" > out.txt
  • >>: Append output to a file. It works same as > if file is empty or not exist.
    • echo "Goodbye, Wolrd!" >> out.txt
  • <: Take input from a file
    • cmd < in.txt
  • Pipes (|): Take output of first command as the input of second command, connecting stdin and stdout.
    • cmd1 | cmd2