Craig Francis


Shell Scripting

Used with BASH

#!/bin/bash

set -u;

ls > /tmp/file; # stdout to file
ls 1> /tmp/file; # stdout to file
ls >> /tmp/file; # stdout to file (append)
ls 2> /dev/null; # stderr to null
ls &> /dev/null; # stdout and stderr to null
ls >> /tmp/file 2>&1; # stdout and stderr to file

command < input-file > output-file;

timestamp=$(date '+%Y-%m-%d %H-%M-%S');

echo 'abcdefg' | sed 's/[b-f]/#/g';

echo '1234321' | awk '{sub("^[1-3]*", "#"); print }';
echo 'abcdefg' | awk '{print substr($0, length($0) - 2)}';
echo 'a b c d' | awk '{split($0, a, " "); print a[2]}';

printf 'a\nb\nc' | tr -d '\n';
printf 'a\nb\nc' | tr '\n' ',';

if [[ "${a}" == "a" ]] && [[ "${b}" == "b" ]]; then
  echo "Both";
fi

if [[ "${a}" == "a" ]] || [[ "${b}" == "b" ]]; then
  echo "Either";
fi

{ cat "/path/to/file.txt"; echo; } | while read line; do
  if [[ "$line" != "" ]]; then
    echo "${line}";
  fi
done

while read -r -d $'\0' file; do
  echo "${file}";
done < <(find "${src}" -mindepth 1 -maxdepth 1 -print0);
path_lock="/tmp/lock-file"

if [ -e "${path_lock}" ]; then
  c=$(pgrep -f -F "${path_lock}" 'backup' 2>/dev/null | wc -l);
else
  c=0;
fi

if [[ "${c}" -gt 0 ]]; then
  if tty -s; then
    echo "Already running";
  fi;
  exit;
fi;

echo "$$" > "${path_lock}";

# ...

if [[ ! -e "${path_lock}" ]] || ! grep -q "$$" "${path_lock}";
then
  echo "$(date) : Lost Lock";
  exit;
fi

String

Operator Meaning
if [[ "$a" == "$b" ]]; Equal to
if [[ "$a" != "$b" ]]; Not equal to
if [[ "$a" < "$b" ]]; Less than (ASCII)
if [[ "$a" > "$b" ]]; Greater than (ASCII)
if [[ -z "$b" ]]; String is empty
if [[ -n "$b" ]]; String is not empty

Arithmetic

Operator Meaning
if (( "$a" == "$b" )); Equal to
if (( "$a" != "$b" )); Not Equal to
if (( "$a" < "$b" )); Less than
if (( "$a" <= "$b" )); Less than or equal to
if (( "$a" > "$b" )); Greater than
if (( "$a" >= "$b" )); Greater than or equal to
 
a=$(( 20 + 5 )) Integer arithmetic, with assignment
(( a = 78 )) C-style variable assignment
(( a++ )) C-style variable increment
(( a-- )) C-style variable decrement
(( b = a < 98 ? 9 : 21 )) C-style ternary operation
 
if [ "$a" -eq "$b" ]; Equal to
if [ "$a" -ne "$b" ]; Not equal to
if [ "$a" -lt "$b" ]; Less than
if [ "$a" -le "$b" ]; Less than or equal to
if [ "$a" -gt "$b" ]; Greater than
if [ "$a" -ge "$b" ]; Greater than or equal to

File

Operator Meaning
-e File exists
-f File is a regular file
-d File is a directory
-h File is a symbolic link
-L File is a symbolic link
-b File is a block device
-c File is a character device
-p File is a pipe
-S File is a socket
-t File is associated with a terminal
 
-N File modified since it was last read
-O You own the file
-G Group id of file same as yours
 
-s File is not zero size
 
-r File has read permission
-w File has write permission
-x File has execute permission
 
-g sgid flag set
-u suid flag set
-k "sticky bit" set
 
F1 -nt F2 File F1 is newer than F2
F1 -ot F2 File F1 is older than F2
F1 -ef F2 Files F1 and F2 are hard links to the same file

Special Variables

Operator Meaning
${0} Filename of script
${1} Positional parameter #1
${10} Positional parameter #10
${#*} Number of positional parameters
${#@} Number of positional parameters
"$*" All the positional parameters (as a single word) *
"$@" All the positional parameters (as separate strings)
$? Return value
$$ Process ID (PID) of script
$- Flags passed to script (using set)
$_ Last argument of previous command
$! Process ID (PID) of last job run in background

Constructs

Operator Meaning
if [[ CONDITION ]] Extended test construct
if [ CONDITION ] Test construct
${variable} Parameter substitution
${!variable} Indirect variable reference
{ cmd1; cmd2; ... cmdN; } Block of code
{str1, str2, ... strN} Brace expansion
{a..z} Extended brace expansion
 
( command1; command2 ) Command group execution, in subshell
Array=(e1 e2 e3) Array initialisation
 
result=$(COMMAND) Command substitution, new style
 
>(COMMAND) Process substitution
<(COMMAND) Process substitution
 
"$variable" "Weak" quoting
'string' 'Strong' quoting

Parameter Substitution and Expansion

Operator Meaning
${var} Value of var (same as $var)
 
${var-$DEFAULT} If var not set, evaluate expression as $DEFAULT *
${var:-$DEFAULT} If var not set or is empty, evaluate expression as $DEFAULT *
 
${var=$DEFAULT} If var not set, evaluate expression as $DEFAULT *
${var:=$DEFAULT} If var not set or is empty, evaluate expression as $DEFAULT *
 
${var+$OTHER} If var set, evaluate expression as $OTHER, otherwise as null string
${var:+$OTHER} If var set, evaluate expression as $OTHER, otherwise as null string
 
${var?$ERR_MSG} If var not set, print $ERR_MSG and abort script with an exit status of 1.*
${var:?$ERR_MSG} If var not set, print $ERR_MSG and abort script with an exit status of 1.*
 
${!varprefix*} Matches all previously declared variables beginning with varprefix
${!varprefix@} Matches all previously declared variables beginning with varprefix

String Operations

Operator Meaning
${#string} Length of $string
 
${string:position} Extract substring from $string at $position
${string:position:length} Extract $length characters substring from $string at $position [zero-indexed, first character is at position 0]
 
${string#substring} Strip shortest match of $substring from front of $string
${string##substring} Strip longest match of $substring from front of $string
${string%substring} Strip shortest match of $substring from back of $string
${string%%substring} Strip longest match of $substring from back of $string
 
${string/substring/replacement} Replace first match of $substring with $replacement
${string//substring/replacement} Replace all matches of $substring with $replacement
${string/#substring/replacement} If $substring matches front end of $string, substitute $replacement for $substring
${string/%substring/replacement} If $substring matches back end of $string, substitute $replacement for $substring
 
expr match "$string" '$substring' Length of matching $substring* at beginning of $string
expr "$string" : '$substring' Length of matching $substring* at beginning of $string
expr index "$string" $substring Numerical position in $string of first character in $substring* that matches [0 if no match, first character counts as position 1]
expr substr $string $position $length Extract $length characters from $string starting at $position [0 if no match, first character counts as position 1]
expr match "$string" '\($substring\)' Extract $substring*, searching from beginning of $string
expr "$string" : '\($substring\)' Extract $substring* , searching from beginning of $string
expr match "$string" '.*\($substring\)' Extract $substring*, searching from end of $string
expr "$string" : '.*\($substring\)' Extract $substring*, searching from end of $string