Skip to search
← Back to traw.shContribute on GitHub ↗
TRAW’S FIELD NOTES / BASH

A few notes.
A lot of Bash.

I wrote these while finding my way around the shell. Now they’re here for the next time I forget how something works. Maybe they’ll save you a search, too.

Less remembering.
More making things work.
13 topics · 120 reference cards
01 / 10 CARDS

Getting started

Variables, arguments, and the basics.

Edit these notes ↗

Variables

bash
NAME="TRAW"

echo ${NAME}    # => TRAW :This prints the variable value
echo $NAME      # => TRAW :This prints the variable value
echo "$NAME"    # => TRAW :This prints the variable value
echo '$NAME'    # => $NAME : This will print the Exact string not value.
echo "${NAME}!" # => TRAW! :Concatenation of variable value with !

# Note: When declaring variables there should be no spaces between the variable
# name and equal sign and between the equal sign and the variable value.
# this will throw and error
NAME = "TRAW"   # => Error (about space)

💡 It is crucial to keep in mind that when referencing a variable value, the dollar sign is used, but when referencing the variable to assign a value, the dollar sign is not used.

Special parameters

ParameterDescription
$1… $9Parameters 1 to 9.
$0Stores the name of the script file or the current shell name.
$1represents the first argument.
${10}Positional parameter 10.
$#Number of positional parameters
$*stores all the arguments.
$$Process id of the current shell.
$@All arguments, starting from first.

Special parameters · continued

ParameterDescription
$-Current options.
$_Last argument of the previous command
$!The process ID (PID) of the most recently executed background pipeline (like started with command &)
$?Status of the most recently executed foreground-pipeline (exit/return code)

Comments

bash
# This is an inline Bash comment.
: '
This is a
Multi-line comment
in bash

If it looks very neat
'

# **Note you can replace the single quoations with**
# **double qoutations**

💡 For Multi-line comments use :' to open and ' to close.

Functions

bash
#!/usr/bin/env bash

get_username() {
    echo "TRAW"
}

# Or using the function keyword
function get_username() {
    echo "TRAW"
}

echo "You are $(get_username)"

Example script

bash
#!/usr/bin/env bash

greet="world World"
echo "$greet!, I'm new here."
# => Hello world! I'm new here.

#Execute the script

$ chmod +x helloworld.sh
$ ./helloworld.sh

# or just

$ bash helloworld.sh

Conditions

bash
#!/usr/bin/env bash

string="test"

if [[ -z "$string" ]]; then
    echo "String is empty"
elif [[ -n "$string" ]]; then
    echo "String is not empty"
fi
02 / 8 CARDS

Parameter expansion

A little more out of your variables.

Edit these notes ↗

Syntax

SyntaxDescription
${parameter%suffix}Remove suffix
${parameter#prefix}Remove prefix
${parameter%%suffix}Remove long suffix
${parameter##prefix}Remove long prefix
${parameter/pattern/string}Replace first pattern match with string
${parameter//pattern/string}Replace all the pattern with string
${parameter/%pattern/string}Replace suffix pattern with string
${parameter/#pattern/string}Replace prefix patter with string

Substrings

${FOO:0:3}Substring (position, length)
${FOO:(-3):3}Substring from the right

Default values

${FOO:-val}$FOO, or val if unset
${FOO:=val}Set $FOO to val if unset
${FOO:+val}val if $FOO is set
${FOO:?message}Show message and exit if $FOO is unset

Substitution

bash
echo ${food:-Cake}  #=> $food or "Cake"
STR="/path/to/foo.cpp"
echo ${STR%.cpp}    # /path/to/foo
echo ${STR%.cpp}.o  # /path/to/foo.o
echo ${STR%/*}      # /path/to

echo ${STR##*.}     # cpp (extension)
echo ${STR##*/}     # foo.cpp (basepath)

echo ${STR#*/}      # path/to/foo.cpp
echo ${STR##*/}     # foo.cpp

echo ${STR/foo/bar} # /path/to/bar.cpp

Basepath & Dirpath

bash
SRC="/path/to/foo.cpp"
BASEPATH=${SRC##*/}
echo $BASEPATH  # => "foo.cpp"

DIRPATH=${SRC%$BASEPATH}
echo $DIRPATH   # => "/path/to/"

Slicing

bash
name="John"
echo ${name}           # => John
echo ${name:0:2}       # => Jo
echo ${name::2}        # => Jo
echo ${name::-1}       # => Joh
echo ${name:(-1)}      # => n
echo ${name:(-2)}      # => hn
echo ${name:(-2):2}    # => hn

length=2
echo ${name:0:length}  # => Jo

Transform

bash
STR="HELLO WORLD!"
echo ${STR,}   # => hELLO WORLD!
echo ${STR,,}  # => hello world!

STR="hello world!"
echo ${STR^}   # => Hello world!
echo ${STR^^}  # => HELLO WORLD!

ARR=(hello World)
echo "${ARR[@],}" # => hello world
echo "${ARR[@]^}" # => Hello World

💡 Read more about bash parameter expansions here:

03 / 18 CARDS

Arrays

Lists, keys, and working with collections.

Edit these notes ↗

Array Declaration syntax

SyntaxDescription
ARRAY=()Declares an indexed array ARRAY and initializes it to be empty. This can also be used to empty an existing array.
ARRAY[0]=Generally sets the first element of an indexed array. If no array ARRAY existed before, it is created.
declare -a ARRAYDeclares an indexed array ARRAY. An existing array is not initialized.
declare -A ARRAYDeclares an associative array ARRAY. This is the one and only way to create associative arrays in bash.

Indexes and Metadata

${ARRAY[0]}get the first element (refer to Getting values table)
${ARRAY[-1]}get the last element (refer to Getting values table)
${ARRAY[*]}get all the elements (refer to Getting values table)
${ARRAY[@]}get all the elements as well(refer to Getting values table)
${#ARRAY[@]} ${#ARRAY[*]}Expands to the number of elements in ARRAY
${#ARRAY}Expand to the length of the first element.
${#ARRAY[N]}Expands to the length of an individual array member at index N. If the Nth element is a string it gets the (stringlength)
${#ARRAY[STRING]}Expands to the length of an individual associative array member at index STRING (stringlength)
${#ARRAY[@]:N:M} ${#ARRAY[*]:N:M}Expands to the number of elements to M starting from N . The M can be omitted and the it will expand from N up to the last element.

Indexes and Metadata · continued

${ARRAY[0]}get the first element (refer to Getting values table)
${!ARRAY[@]} ${!ARRAY[*]}Expands to the indexes in ARRAY since BASH 3.0

Destroying Arrays

The unset builtin command is used to destroy (unset) arrays or individual elements of arrays.

SyntaxDescription
unset -v ARRAY unset -v ARRAY[@] unset -v ARRAY[*]Destroys a complete array
unset -v 'ARRAY[N]'Destroys the array element at index N . Always quote the array name and index.
ARRAY=( ${ARRAY[@]/STR*/} ) ARRAY=( ${ARRAY[*]/STR*/} )Remove values by regular expressions (STR short for string)
unset -v ARRAY[STRING]Destroys the array element of the associative array at index STRING

Storing Values

SyntaxDescription
ARRAY[N]=VALUESets the element N of the indexed array ARRAY to VALUE. N can be any valid arithmetic expression.
ARRAY[STRING]=VALUESets the element indexed by STRING of the associative array ARRAY.
ARRAY=VALUEAs above. If no index is given, as a default the zeroth element is set to VALUE. Careful, this is even true of associative arrays - there is no error if no key is specified, and the value is assigned to string index "0".
ARRAY=(E1 E2 …)Compound array assignment - sets the whole array ARRAY to the given list of elements indexed sequentially starting at zero. The array is unset before assignment unless the += operator is used. When the list is empty (ARRAY=()), the array will be set to an empty array. This method obviously does not use explicit indexes. An associative array can not be set like that! Clearing an associative array using ARRAY=() works.
ARRAY=([X]=E1 [Y]=E2 …)Compound assignment for indexed arrays with index-value pairs declared individually (here for example X and Y). X and Y are arithmetic expressions. This syntax can be combined with the above - elements declared without an explicitly specified index are assigned sequentially starting at either the last element with an explicit index, or zero.
ARRAY=([S1]=E1 [S2]=E2 …)Individual mass-setting for associative arrays. The named indexes (here: S1 and S2) are strings.
ARRAY+=(E1 E2 …) ARRAY=("${ARRAY[@]}" E1 ...)Append to ARRAY.
ARRAY=("${ANOTHER_ARRAY[@]}")Copy ANOTHER_ARRAY to ARRAY, copying each element. You can omit the quotations: ARRAY=(${ANOTHER_ARRAY[@]})

Storing Values · continued

SyntaxDescription
ARRAY=("$ARRAY[@]}" "${ANOTHER_ARRAY[@]}")Concatenating Arrays. Quotations can be omitted : ARRAY=($ARRAY[@]} ${ANOTHER_ARRAY[@]}) and you can also replace @ with *
ARRAY=($(cat file))storing array values from reading a file.
ARRAY=({N..M})Getting array values from brace expansion N and M can be strings or numeric values (see Array Discussion)

Getting values

SyntaxDescription
${ARRAY[N]}Expands to the value of the index N in the indexed array ARRAY. If N is a negative number, it's treated as the offset from the maximum assigned index (can't be used for assignment) - 1
${ARRAY[S]}Expands to the value of the index S in the associative array ARRAY.
"${ARRAY[@]}" ${ARRAY[@]} "${ARRAY[*]}" ${ARRAY[*]}Similar to mass-expanding positional parameters, this expands to all elements. If unquoted, both subscripts * and @ expand to the same result, if quoted, @ expands to all elements individually quoted, * expands to all elements quoted as a whole (tested all these scenarios, but they don’t seem to produce intended results on my version of bash).
"${ARRAY[@]:N:M}" ${ARRAY[@]:N:M} "${ARRAY[*]:N:M}" ${ARRAY[*]:N:M}Similar to what this syntax does for the characters of a single string when doing substring expansion, this expands to M elements starting with element N. This way you can mass-expand individual indexes. The rules for quoting and the subscripts * and @ are the same as above for the other mass-expansions.

🔗 For clarification: When you use the subscripts @ or * for mass-expanding, then the behavior is exactly what it is for $@ and $* when mass-expanding the positional parameters. You should read this article to understand what's going on.

💡 It is best to explicitly specify -v when unsetting variables with unset.

💡 Learn more about bash Arrays here

Compound indexed array assignment

bash
#
:'
Compound array assignment - sets the whole array
NAMES to the given list of elements.
'
# NAMES => Creg Jan Anna
NAMES=('Creg' 'Jan' 'Anna')

# using the declare construct
declare -a Numbers=(1 2 3)

Index array assignment

bash
:'
Sets the element N of the indexed array NAMES to
VALUE.
N can be any valid arithmetic expression.
'

NAMES[0]='Creg'
NAMES[1]='Jan'
NAMES[2]='Anna'
# NAMES => Creg Jan Anna

Appending values to arrays

bash
NAMES=('Creg' 'Jan' 'Anna')

NAMES+=('Jay' 'Jimmy' 'Tom')
# NAMES => Creg Jan Anna Jay Jimmy Tom

# This is also the same as
NAMES=(${NAMES[@]} 'Jay' 'Jimmy' 'Tom')
# NAMES => Creg Jan Anna Jay Jimmy Tom

Compound associative array assignment

bash
:'
Individual mass-setting for **associative arrays**.
The named indexes (here: name, age....) are strings.
'

declare -A person # this line is required
# quotes can me omitted for the keys, see the **age** key below
person=(["name"]="Jay" [age]=22 ["eye_color"]="blue")

# person => Jay 22 blue

Merging/Concatenating Arrays

bash
ARRAY1=(foo{1..2}) # => foo1 foo2
ARRAY2=({A..D})    # => A B C D
ARRAY3=({1..5})    # => 1 2 3 4 5

# Merge Arrays => foo1 foo2 A B C D 1 2 3 4 5
ARRAY4=(${ARRAY1[@]} ${ARRAY2[@]} ${ARRAY3[@]})

The **@** can also be replace with a *****

Iterating an indexed array

bash
names=('Jay' 'Joe' 'Jimmy')
for name in "${names[@]}"; do
    echo $name
done

# using index
for i in "${!names[@]}"; do
  printf "%s\t%s\n" "$i" "${names[$i]}"
done

Working with associative arrays

bash
declare -A person
person=(["name"]="Jay" [age]=22 ["eye_color"]="blue")

echo ${person[name]} #  Get person's name
echo ${sounds[@]}   # Get all person's values
echo ${sounds[*]}  # Get all person's values
echo ${!person[@]}  # All person's  keys (age, name...)
echo ${#person[@]}  # Number of elements

unset -v person[age]   # Delete person's age

# All of the above operations workes with index arrays, just that you only
# replace the keys with indexes

Iterating an associative array

bash
declare -A person
person=(["name"]="Jay" [age]=22 ["eye_color"]="blue")

for value in "${person[@]}"; do
    echo $value
done

# Using keys
for key in "${!person[@]}"; do
    echo "$key  ${person[$key]}"
done

Array arguments

bash
function extract()
{
    # creating a local array from function argument 1 ($1)
    local -n local_names=$1
	  # creating a local index from function argument 2 ($2)
    local index=$2
    echo "${local_names[$index]}"
 }
# defining global array names
names=('Jay' 'Joe' 'Jimmy')

extract names 2     # => Jimmy
04 / 9 CARDS

Conditions & flow control

Tests, comparisons, and decisions.

Edit these notes ↗

Numeric conditions

ConditionDescription
[[ INTERGER1 -eq INTEGER2 ]]INTEGER1 is equal to INTEGER2
[[ INTEGER1 -ne INTEGER2 ]]INTEGER1 is not equal to INTEGER2
[[ INTEGER1 -lt INTEGER ]]INTEGER1 is less than INTEGER2
[[ INTEGER1 -le INTEGER2 ]]INTEGER1 is less than or equal to INTEGER2
[[ INTEGER1 -gt INTEGER2 ]]INTEGER1 is greater than INTEGER2
[[ INTERGER1 -ge INTEGER2 ]]INTEGER1 is greater than or equal to INTEGER2
(( INTEGER1 < INTEGER2 ))INTEGER1 is less than INTEGER2
(( INTEGER1 <= INTEGER2 ))INTEGER1 is less than INTEGER2

Numeric conditions · continued

ConditionDescription
(( INTEGER1 > INTEGER2 ))INTEGER1 is greater than INTEGER2
(( INTEGER1 >= INTEGER2 ))INTEGER1 is greater than or equal to INTEGER2
(( INTEGER1 == INTEGER2 ))INTEGER1 is equal to INTEGER2
(( INTEGER1 != INTEGER2 ))INTEGER1 is not equal to INTEGER2

String conditions

ConditionDescription
[[ -z STR ]]Empty string
[[ -n STR ]]Not empty string
[[ STR == STR ]]Equal
[[ STR = STR ]]Equal (Same above)
[[ STR < STR ]]Less than (ASCII)
[[ STR > STR ]]Greater than (ASCII)
[[ STR != STR ]]Not Equal
[[ STR =~ REGEXP ]]Regexp

More conditions

ConditionDescription
[[ -o noclobber ]]If OPTION is enabled.
EXPRexpression is true
! EXPRnegate expression

File conditions

ConditionExpression
[[ -b FILE ]]FILE exists and is block special
[[ -c FILE ]]FILE exists and is character special
[[ -d FILE ]]FILE exists and is a directory
[[ -e FILE ]]FILE exists
[[ -f FILE ]]FILE exists and is a regular file
[[ -g FILE ]]FILE exists and is set-group-ID
[[ -G FILE ]]FILE exists and is owned by the effective group ID
[[ -h FILE ]]FILE exists and is a symbolic link (same as -L)

File conditions · continued

ConditionExpression
[[ -k FILE ]]FILE exists and has its sticky bit set
[[ -L FILE ]]FILE exists and is a symbolic link (same as -h)
[[ -N FILE ]]FILE exists and has been modified since it was last read
[[ -O FILE ]]FILE exists and is owned by the effective user ID
[[ -p FILE ]]FILE exists and is a named pipe
[[ -r FILE ]]FILE exists and the user has read access
[[ -s FILE ]]FILE exists and has a size greater than zero
[[ -S FILE ]]FILE exists and is a socket

File conditions · continued

ConditionExpression
[[ -t FD ]]file descriptor FD is opened on a terminal
[[ -u FILE ]]FILE exists and its set-user-ID bit is set
[[ -w FILE ]]FILE exists and the user has write access
[[ -x FILE ]]FILE exists and the user has execute (or search) access
[[ FILE1 -nt FILE2 ]]FILE1 is newer (modification date) than FILE2
[[ FILE1 -ot FILE2 ]]FILE1 is older than FILE2
[[ FILE1 -ef FILE2 ]]FILE1 and FILE2 have the same device and inode numbers or both files are the same

Compound conditions

ConditionDescription
[[ condition1 ]] && [[ condition2 ]]Evaluate to True if both conditions are TRUE
[[ condition1 ]] || [[ condition2 ]]Evaluate to True if either one of the conditions TRUE
[ condition1 -a condition2 ]Evaluate to True if both conditions are TRUE
[ condition1 -o condition2 ]Evaluate to True if either one of the conditions TRUE

💡 Note: It is worth mentioning that you can replace all the double square brackets with single square brackets for example : [[ NUM -eq NUM ]] can also be written as [ NUM -eq NUM ] . This works with all the all conditions except for compound conditions which uses -a (AND) and -o (OR) as logical operators.

Advanced if-then Features

  • Single parentheses (.......) allow you to use subshells in your if statement comparisons.
  • The double parentheses (( epression )) command allows you to incorporate advanced mathematical formulas in your comparisons. check out performing arithmetic operations.
  • The double bracket [[.......]] command provides advanced features for string comparisons.
05 / 9 CARDS

Loops

Doing things more than once.

Edit these notes ↗

Bash for loop

bash
for i in /etc/*; do
    echo $i
done

# Same as above(alternate syntax), also works with other loop structs

for i in /etc/*
do
		echo $i
done

Bash while loop

bash
# incrementing the value
i=1
while [[ $i -lt 4 ]]; do
    echo "Number: $i"
    ((i++))
done

 # decrementing the value

i=3
while [[ $i -gt 0 ]]; do
    echo "Number: $i"
    ((i--))
done

Continue statement

bash

# seq command can be using to gerate ranges

for number in $(seq 1 3); do
    if [[ $number == 2 ]]; then
        continue;
    fi
    echo "$number"
done

C-like for loop

bash
for ((i = 0 ; i < 100 ; i++)); do
    echo $i
done

# Same as above (alternate syntax) also works with other loop structs

for ((i = 0 ; i < 100 ; i++))
do
    echo $i
done

Bash while True loop

bash
# while true long hand

while true; do
    # TODO
		# TODO
done

# or the shorthand (alternate syntax)

while :; do
    # TODO
		# TODO
done

Break statement

bash

for number in $(seq 1 3); do
    if [[ $number == 2 ]]; then
        # Skip entire rest of loop or break out of the loop.
        break;
    fi
    # This will only print 1
    echo "$number"
done

Ranges

bash
for i in {1..10}; do
    echo "Number: $i"
done

# With step size
# => {START..STOP..STEP}

for i in {5..50..5}; do
    echo "Number: $i"
done

Reading files with while loop

bash
# using pipes

cat file.txt | while read line; do
    echo $line
done

# OR using input redirection

while read line; do
		echo $line
done < "/path/to/txt/file"

Until or do loop

bash
# incrementing
count=0
until [ $count -gt 10 ]; do
    echo "$count"
    ((count++))
done

# decremetning
count=10
until [ $count -eq 0 ]; do
    echo "$count"
    ((count--))
done
06 / 3 CARDS

Functions

Small pieces you can use again.

Edit these notes ↗

Defining functions

bash
greet() {
    echo "hello $1 $2"
}

# Same as above (alternate syntax)
function greet() {
    echo "hello $1 $2"
}

# Calling the function
greet "John" "Paul"

Returning values

bash
add_numbers() {

		# perfoming mathematical additions
    local result=$(( $1 + $2)

		# returning the sresult value
    echo $result
}

# storing the returned value
result="$(add_numbers 1 2)"

Raising errors

bash
# using return
myfunc() {
    return 1
}

if myfunc; then
    echo "success"
else
    echo "failure"
fi
07 / 6 CARDS

Arithmetic

Working with numbers in the shell.

Edit these notes ↗

Bash Arithmetic Operators

Arithmetic OperatorDescription
+, -Addition and subtraction
*, /, %Multiplication, division, and remainder (modulo)
**Exponentiation
<=, >=, <, >Less than or equal, greater than or equal , less than, and greater than.
==, !=Equality (equal to) and inequality (not equal to)
=, *=, /=, %=, +=, -=, «=, »=, &=, ^=, |=Assignment operators
id++, id --Variable post-increment and post-decrement
++id, --idVariable pre-increment and pre-decrement

Bash Arithmetic Operators · continued

Arithmetic OperatorDescription
&&Logical AND
||Logical OR
-, +Unary minus, plus
!, ~Logical and bitwise negation
«, »Left and right bitwise shifts
&Bitwise AND
^Bitwise XOR
|Bitwise OR

Using expr to perform arithmetic operations

bash
#!/bin/bash

# Basic arithmetic using expr
:"
Because expr is a binary rather than a shell builtin, this method may be slow. In a large for-loop,
it will fork a new process, which is undesirable. Furthermore, depending on the implementation, the behavior
of expr may differ between systems.

In contrast to let, you do not need to enclose the expression in quotes. There must also be spaces between
the expression's items. To save the output to a variable, like any other command you can use command
substitution to capture the output of expr into a variable.
"

# expr syntax
expr item1 operator item2

# Note that there must be spaces between the items and no quotes.
expr 7 + 5 #=> 13

expr "6 + 3" #=> 6 + 3

# if you put qoutes the expression will not be evaluated but printed instead.
expr 3+2 #=> 3+2

# The asterisk has special meaning in bash so we must escape it using \ to remove its special meaning.
expr 5 \* 3

# modulus operator demonstration
expr 15 % 2 #=> 1

# using command substitution to save output to a variable
result=$( expr 15 - 2 )
echo $result #=> 13

💡 The square brackets $[...]can also do Arithmetic Expansion in Bash, though this notation has been deprecated and should be avoided. Instead, prefer the use of $((...)) instead.

Like let you can also use the declarebuiltin with the -i option to do arithmetic operations

Using let to perform arithmetic operations

bash
#!/bin/bash

# Basic arithmetic using let
:"
let is a Bash built-in function that allows us to perform simple arithmetic.

The arithmetic expression can take several forms, which we'll go over below. However, the first part is
always a variable into which the result is saved.
"

# The let has the following syntax:
let <arithmetic expression>

# It is important to note that if we do not use quotes around the expression, it must be written without
# spaces.
let result=6+4
echo $result #=> 10

# This time, we used quotes to space out the expression and make it more readable.
let "result = 4 + 4"
echo $result #=> 8

# incremeting the result same as let result =result+1 or let result+=1
let result++
echo $result #=> 9

# doing some multiplication
let "result = 4 * 5"
echo $result # 20

# We can also use variables in expressions
let "result = $1 + 30"
echo $result # 30 + first command line argument

Using double parentheses for arithmetic operations

bash
#!/bin/bash

# Basic arithmetic using double parenthesis

:"
The Arithmetic Expansion capability of the shell is the recommended way for evaluating arithmetic expressions
with integers in Bash. The built-in shell expansion allows you to perform math calculations by using
 parentheses ((...)).
"

# The Bash arithmetic expansion is written in the format:
$((arithmetic expression))

# you can space out without the need for quotaions to improve readabilty
result=$(( 6 + 5 ))
echo $result #=> 11

# this works the same
result=$((3+7))
echo $result #=> 10

# you can include other variables without the need of using $ on them, notice **result** variable below.
result2=$(( result + 3 ))
echo $result2 #=> 11

# you can inlcude variables with $ if you prefer.
result2=$(( $result + 4 ))
echo $result2 #=> 14

# when incrementing the variable you don't include the $ sign
(( result2++ ))
echo $result2 #=> 15

# incrementing the value by 3 this is the shorthand for result2 = result2 + 4.
(( result2 += 4 ))
echo $result2 #=> 19

# Unlike other methods, when we do multiplication we don't need to escape the * sign. This what makes this
# method so powerful and versatile.
result=$(( 4 * 5 ))
echo $result #=> 20
08 / 4 CARDS

Chaining commands

Connecting commands and their results.

Edit these notes ↗

Overview

Below are some commonly used chaining operators which you can use with different commands:

Overview

Chaining OperatorDescription
& (Ampersand)This sends a command, script, or process to the background. In short, it makes a command run in the background.
&& (Logical AND)The && operator will only execute the second command if the first command SUCCEEDS! , in other words, if the first command exits with a zero status.
|| (Logical OR)Execute the second command only if the first command fails with a non-zero exit status.
; (Semi-colon)The command following this operator will execute even if the command preceding this operator is not successfully executed.
! (NOT)Negate the exit status of a pipeline. It still runs the command.
a && b || c (AND-OR)Run b if a succeeds; run c if a or b fails. This is not an exact substitute for if/else.
| (Pipe)Send the standard output of one command to the standard input of the next.
>,>>, < (Input-OutputRedirection)Redirects the output of a command or a group of commands to a file or stream.

Overview · continued

Chaining OperatorDescription
\ (Concatenation)Used to concatenate large commands over several lines in the shell.
( commands ) (Subshell)Run a group of commands in a subshell environment.
{ commands; } (Group)Run a group of commands in the current shell. Include spaces around the braces and a semicolon or newline before the closing brace.
09 / 8 CARDS

Redirections

Getting input and output where they belong.

Edit these notes ↗

Here documents

A here document spans multiple lines. Quote the delimiter to keep the body literal rather than expanding variables and command substitutions.

bash
cat <<'EOF'
A line of text.
Another line of text.
EOF

Standard file descriptors

File DescriptorAbbreviationDescription
0STDINStandard input, The input is read from what you type in the terminal using your keyboard. When you use the input redirect symbol (<), Linux substitutes the file referenced by the redirection for the standard input file descriptor. It reads the file and retrieves data in the same way that you would type it on a keyboard.
1STDOUTStandard Output. The terminal monitor is the standard output on a terminal interface. All output from the shell (including programs and scripts run in the shell) is directed to the monitor's standard output. When you use the output redirect symbol (>), Linux replaces the terminal with a file referenced by the redirection symbol.
2STDERRStandard Error. The STDERR file descriptor, by default, points to the same location as the STDOUT file descriptor (despite being assigned different file descriptor values). This means that by default, all error messages are displayed on the monitor. To redirect the errors you use a special redirection operator 2> .

💡 Unless they are closed, file descriptors always point to a file. When bash starts, all three file descriptors, stdin (file descriptor 0), stdout (file descriptor 1), and stderr (file descriptor 2), usually point to your terminal.

You can also open and close additional file descriptors (such as 3, 4, 5,...). File descriptors can also be copied. You can also write to and read from them.

Redirections Operators

RedirectionDescription
command > fileRedirect the standard output (stdout) of a command to a specified file. This also the same as command 1> file , as 1 is the default file descriptor (fd) for standard output (stdout).
command 2> fileRedirect the standard error (stderr) of a command to a specified file. 2 is the default file descriptor (fd) for standard error (stderr).
command >> fileRedirect the standard output (stdout) of a command to a specified file without overriding the existing data.
command 2>> fileRedirect the standard error (stderrt) of a command to a specified file without overriding the existing data.
command &> fileRedirect both stdout and stderr to a file. Equivalent to command > file 2>&1, but not command 2>&1 > file: redirections are applied from left to right.
command > /dev/nullDiscard standard output (stdout) of a command. The /dev/null is a special file that discards all data written to it.
command 2> /dev/nullDiscard standard error (stderr) of a command.
command &> /dev/nullDiscard both the standard output (stdout) and the standard error (stderr) of a command. This also the same as command >/dev/null 2>&1.

Redirections Operators · continued

RedirectionDescription
command < fileRedirect the contents of the file to the standard input (stdin) of a command. This also the same as command 0< file . 0 is the default file descriptor (fd) for standard input (stdin).
command << MARKERRead a here document until a line containing only MARKER. See the multiline example below.
command <<- MARKERRead a here document and strip leading tab characters (not spaces).
command <<< 'string' command <<< $wordThe here string is used for input redirection from a single line of text or a variable. A here string can be considered as a stripped-down form of here document
command >| fileOverrides the noclobber shell option ( Bash options)
exec 2> fileRedirect standard error of all commands to a file forever.
exec > fileRedirect standard output of all commands to a file forever.
exec 3< fileCreate a custom file descriptor (3) for reading from a file

Redirections Operators · continued

RedirectionDescription
exec 3> fileCreate a custom file descriptor (3) for writing to a file
exec 3<> fileCreate a custom file descriptor (3) for both writing and reading a file
exec 3>&-Close the created file descriptor.
exec 4<&3Make file descriptor 4 to be a copy of file descriptor 3. (Copy fd 3 to 4.)
exec 4>&3-Copy file descriptor 3 to 4 and close file descriptor 3.
echo "foo" >&3Write to a custom file descriptor 3.
cat <&3Read from a custom file descriptor 3.
exec 3<> /dev/tcp/host/portOpen a TCP connection to host:port. (This is a bash feature, not Linux feature).

Redirections Operators · continued

RedirectionDescription
exec 3<> /dev/udp/host/portOpen a UDP connection to host:port. (This is a bash feature, not Linux feature).
(command1; command2) > fileRedirect stdout from multiple commands to a file (using a sub-shell). The parenthesis instructs bash to create a subshell and run commands from there.
{ command1; command2; } > fileRedirect stdout from a group of commands in the current shell. Include a semicolon or newline before the closing brace, and spaces around the braces.
command <(command1)Redirect stdout of command1 to an anonymous pipe fifo, then pass the fifo to command as an argument. Useful when command doesn’t read from stdin directly.
command < < (command1)Redirect stdout of command to an anonymous pipe fifo, then redirect the fifo to stdin of command. Best example: diff <(find /path1 | sort) <(find /path2 | sort).
command <(command1) <(command2)Redirect stdout of command1 and command2 to two anonymous fifos, then pass both fifos as arguments to command.
command1 >(command2)Run command2 with its stdin connected to an anonymous fifo, and pass the filename of the pipe as an argument to command1.
command1 > > (command2)Run command2 with its stdin connected to an anonymous fifo, then redirect stdout of command1 to this anonymous pipe.

Redirections Operators · continued

RedirectionDescription
command1 | command2Redirect stdout of command1 to stdin of command2. Pro-tip: This is the same as command1``> > (command2), same as cmd2 < <(cmd1), same as > >(cmd2) cmd1, same as < <(cmd1) cmd2.
command1 |& command2Redirect stdout and stderr of command1 to stdin of command2 (bash 4.0+ only). Use command2>&1 | command2 for older bashes.
commnad | tee fileRedirect stdout of commmand to a file and print it to screen.
exec {filew}> fileOpen a file for writing using a named file descriptor called {filew} (bash 4.1+).
command 3>&1 1>&2 2>&3Swap stdout and stderr of command .
cmd > >(cmd1) 2> >(cmd2)Send stdout of cmd to cmd1 and stderr of cmd to cmd2.
cmd1 | cmd2 | cmd3 | cmd4 echo ${PIPESTATUS[@]}Find out the exit codes of all piped commands.
10 / 11 CARDS

Shell options

Changing how Bash behaves.

Edit these notes ↗

Some options need a newer Bash. Check bash --version; the default shell on macOS may differ.

Overview

💡 Options are settings that change shell or script behaviour. The set builtin command can be use to set options. There are two ways to set options either by set -o option-name or, in short form, set -option-abbrev ****. To disable **an option, use set +o option-name ****or set +option-abbrev ****. To enable option on a script on the command line use, set +o option-name script-name ****or ****set option-abbrev script-name

Overview

AbbreviationNameEffect
-Bbrace expansionEnable brace expansion (default setting = on)
+Bbrace expansionDisable brace expansion
-CnoclobberPrevent overwriting of files by redirection (but this may be overridden by >| )
-D(none)List double-quoted strings prefixed by $, but do not execute commands in script
-aallexportExport all defined variables
-bnotifyNotify when jobs running in background terminate (not of much use in a script)
-c …(none)Read commands from ...
checkjobsInforms user of any open jobs upon shell exit. Introduced in version 4 of Bash, and still "experimental." Usage: shopt -s checkjobs (Caution: may hang!)

Overview · continued

AbbreviationNameEffect
-eerrexitAbort script at first error, when a command exits with non-zero status (except in until or while loops, if-tests, list constructs)
-fnoglobDisable filename expansion (globbing)
globstarglobbing star-matchEnables the ** globbing operator. Usage: shopt -s globstar
-iinteractiveRuns a script in interactive mode
-nnoexecRead commands in script, but do not execute them (syntax check)
-o Option-Name(none)Invoke the Option-Name option
-o posixPOSIXChange the behavior of Bash, or invoked script, to conform to POSIX standard.
-o pipefailpipe failureCauses a pipeline to return the exit status of the last command in the pipe that returned a non-zero return value.

Overview · continued

AbbreviationNameEffect
-pprivilegedScript runs as "suid" (caution!)
-rrestrictedScript runs in restricted mode
-sstdinRead commands from stdin
-tonecmdExit after first command
-unounsetAttempt to use undefined variable outputs error message, and forces an exit
-vverbosePrint each command to stdout before executing it
-xxtraceSimilar to -v, but expands commands
-(none)End of options flag. All other arguments are positional parameters.

Overview · continued

AbbreviationNameEffect
--(none)Unset positional parameters. If arguments given (-- arg1 arg2), positional parameters set to arguments.

Description

💡 The shopt builtin command allows you to change additional shell optional behavior.

shopt options

OptionDescription
-oRestrict the values of <OPTNAME…> to only those also known by the set builtin
-pPrint all shell options and their current value. Default.
-qQuiet mode. Set exit code if named option is set. For multiple options: TRUE if all options are set, FALSE otherwise
-sEnable (set) the shell options named by <OPTNAME…> or list all enabled options if no names are given
-uDisabe (unset) the shell options named by <OPTNAME…> or list all disabled options if no names are given

shopt syntax

🛠 shopt [-pqsu] [-o] <OPTNAME...>

💡 According to the option table, if only -s or -u are specified without any option names, only the currently enabled (-s) or disabled (-u) options are printed.

Exit code

💡 When listing options, the exit code is TRUE (0), if all options are enabled, FALSE otherwise.

When setting/unsetting an option, the exit code is TRUE unless the named option doesn't exitst.

bash
shopt -s nullglob  #Example to enable nullglob option

List of additional shell options

Option nameDescription
autocd

I know using the cd command feels natural but that’s something I wanted to get to your attention. | If set, a command name that is the name of a directory is executed as if it were the argument to the cd command. | | cdspell | If set, minor errors in the spelling of a directory component in a cd command will be corrected. The errors checked for are transposed characters, a missing character, and one character too many. If a correction is found, the corrected file name is printed, and the command proceeds. | | checkjobs | If set, Bash lists the status of any stopped and running jobs before exiting an interactive shell. If any jobs are running, this causes the exit to be deferred until a second exit is attempted without an intervening command. The shell always postpones exiting if any jobs are stopped. | | dirspell | If set, Bash will perform spelling corrections on directory names to match a glob. | | dotglob | If set, Bash includes filenames beginning with a . (dot) in the results of pathname expansion. | | nullglob | If set, Bash allows filename patterns which match no files to expand to a null string, rather than themselves. | | failglob | If set, patterns which fail to match filenames during filename expansion result in an expansion error. | | nocaseglob | If set, Bash matches filenames in a case-insensitive fashion when performing filename expansion. | | globstar | If set, the pattern ‘**’ used in a filename expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a ‘/’, only directories and subdirectories match. |

💡 Here is an exhaustive lists of all the additional options

11 / 6 CARDS

History

Finding that command you ran earlier.

Edit these notes ↗

History commands

CommandDescription
historyDisplay history
history nDisplay only the last n commands from the history
history -cClears your current history and starts adding commands from scratch
history -d nDelete the specified nth command from history
sudo !!Run the previous command with sudo
<space> commandPrevent history from adding the command to history
shopt -s histverifyDon't execute expanded result immediately
echo $HISTSIZEDisplay maximum of commands that can be stored in history file

History modifiers

ModifiersDescription
<word>:hRemove a trailing file name component, leaving only the head from the expanded command.
<word>:rRemove a trailing suffix of the form .xxx, leaving the basename.
<word>:tRemove all leading file name components, leaving the tail.
<word>:eRemove all but the trailing suffix.
<word>:pPrint the new command but do not execute it.
<word>:qQuote the substituted words, escaping further substitutions.
<word>:xQuote the substituted words as with q, but break into words at blanks and newlines. The q and x modifiers are mutually exclusive; the last one supplied is used.
<word>:s/old/new/Substitute new for the first occurrence of old in the event line.

History modifiers · continued

ModifiersDescription
<word>:gs/old/new/Cause changes to be applied over the entire event line. This is used in conjunction with :s'
<word>:&Repeat the previous substitution.
<word>:GApply the following s' or &' modifier once to each word in the event line.

History slices

SlicesDescription
!!:nExpand only nth token from most recent command (command is 0; first argument is 1)
!^Expand first argument from most recent command
!$Expand last token from most recent command
!!:n-mExpand range of tokens from most recent command
!!:n-$Expand nth token to last from most recent command

History event designators

EventDescription
!!Expand the previous command
!-nExpand nth most recent command
!nExpand nth command in history
!<command>Expand most recent invocation of command <command>
!<text>Expand the last command that begins with a specific text
!n:p or !<text>:pPrint the expanded command before executing it.
^string1^string2Expand the last command, replacing string1 with string2.
!#Expand the entire command line typed so far.

History Word designators

💡 Word designators are used to select desired words from the event. A colon “:” separates the event specification from the word designator. Here are some word designators (^, $, *, -, or %)

WordDescription
!$Expand last parameter of most recent command
!*Expand all parameters of most recent command
!^Expand the first parameter of the most recent command
!nExpand nth command in history
!%The first word matched by the most recent `?string?' search, if the search string begins with a character that is part of a word.
!x-yA range of words; -y abbreviates 0-y

💡 Following the optional word designator, one or more of the modifiers listed on the left side may appear, each preceded by a ':'. These change or edit the word or words chosen from the history event.

Remove a trailing file name component, leaving only the head from the expanded command. $ cat demo.sh $ $!:h:p #⇒ this will print demo

12 / 12 CARDS

Built-in commands

Tools that come with the shell.

Edit these notes ↗

Shell Builtins

Built-in commands are distinct in that they do not require the execution of a child process. They were compiled into the shell and thus become part of its toolkit. There is no external program file to run them.

Bash Built‐In Commands #-B

CommandDescription
.same as source builtin. Reads and executes commands from a designated file in the current shell
&Starts a job in background mode
((x))Evaluates the x mathematical expression
not:Reads and executes commands from a designated file in the current shell.
:Does nothing, and always exits successfully, same as true builtin
[ t ]Evaluates the t conditional expression
[[ e ]]Evaluates the e conditional expression
aliasDefines an alias for the specified command

Bash Built‐In Commands #-B · continued

CommandDescription
bgResumes a job in background mode
bindBinds a keyboard sequence to a readline function or macro
breakExits from a for , while , select , or until loop
builtinExecutes the specified shell built‐in command

Bash Built‐In Commands E-F

echoDisplays the specified string to STDOUT
enableEnables or disables the specified built‐in shell command
evalConcatenates the specified arguments into a single command, and executes the command
execReplaces the shell process with the specified command
exitForces the shell to exit with the specified exit status
exportSets the specified variables to be available for child shell processes
falseSets a result to failed status
fcSelects a list of commands from the history list
fgResumes a job in foreground mode

Bash Built‐In Commands G-P

getoptsParses the specified positional parameters
hashFinds and remembers the full pathname of the specified command
helpDisplays a help file
historyDisplays the command history
ifExecutes set commands based on conditional expression
jobsLists the active jobs
killSends a system signal to the specified process ID (PID)
letEvaluates each argument in a mathematical expression
localCreates a limited‐scope variable in a function

Bash Built‐In Commands G-P · continued

getoptsParses the specified positional parameters
logoutExits a login shell
mapfileReads STDIN lines and puts them into an indexed array
popdRemoves entries from the directory stack
printfDisplays text using formatted strings
pushdAdds a directory to the directory stack
pwdDisplays the pathname of the current working directory

Bash Built‐In Commands C-D

callerReturns the context of any active subroutine call
caseSelectively executes commands based on pattern
cdChanges the current directory to the specified directory
commandExecutes the specified command without the normal shell lookup
compgenGenerates possible completion matches for the specified word
completeDisplays how the specified words would be completed
compoptChanges options for how the specified words would be completed
continueResumes the next iteration of a for , while , select , or until loop
coprocExecutes a coprocess

Bash Built‐In Commands C-D · continued

callerReturns the context of any active subroutine call
declareDeclares a variable or variable type
dirsDisplays a list of currently remembered directories
disownRemoves the specified jobs from the jobs table for the process

Bash Built‐In Commands R-#

readReads one line of data from STDIN , and assigns it to a variable
readarrayReads STDIN lines, and puts them into an indexed array
readonlyReads one line of data from STDIN , and assigns it to a variable that can't be changed
returnForces a function to exit with a value that can be retrieved by the calling script
selectDisplays list of words with numbers allowing selection
setSets and displays environment variable values and shell attributes
shiftRotates positional parameters down one position
shoptToggles the values of variables controlling optional shell behavior
sourceReads and executes commands from a designated file in the current shell

Bash Built‐In Commands R-# · continued

readReads one line of data from STDIN , and assigns it to a variable
suspendSuspends the execution of the shell until a SIGCONT signal is received
testReturns an exit status of 0 or 1 based on the specified condition
timeDisplays the accumulated real, user, and system times executing command(s)
timesDisplays the accumulated user and system shell times
trapExecutes the specified command if the specified system signal is received
trueSets a result to successful status
typeDisplays how the specified word would be interpreted if used as a command
typesetDeclares a variable or variable type

Bash Built‐In Commands R-# · continued

readReads one line of data from STDIN , and assigns it to a variable
ulimitSets a limit on the specified resource for system users
umaskSets default permissions for newly created files and directories
unaliasRemoves the specified alias
unsetRemoves the specified environment variable or shell attribute
untilExecutes set commands until condition statement returns true
waitWaits for the specified process to complete, and returns the exit status
whileExecutes set commands while condition statement returns true
{ c; }Group commands to execute within current shell
13 / 16 CARDS

Regular expressions

Patterns, character classes, and matching.

Edit these notes ↗

Regex syntax depends on the tool. Bash’s [[ =~ ]] uses POSIX extended expressions; shorthand classes, lookarounds, and modifiers listed here are not supported everywhere.

Anchors

^Start of string, or start of line in multi-line pattern
\AStart of string
$End of string, or end of line in multi-line pattern
\ZEnd of string
\bWord boundary
\BNot word boundary
\<Start of word
\>End of word

Character classes

[abc]A single character of: a, b or c
[^abc]A character except: a, b or c. The caret ^ negates character classes
[a-z]A character in the range: a-z
[^a-z]A character not in the range: a-z
[0-9]A digit in the range: 0-9
[a-zA-Z]A character in the range:a-z or A-Z
[a-zA-Z0-9]A character in the range:a-z, A-Z or 0-9

Shorthand character classes

\cControl character
\sWhite space
\SNot white space
\dDigit
\DNot digit
\wWord
\WNot word
\xHexade­cimal digit
\OOctal digit

Posix BRE Special Character Classes

ClassSame asDescription
[[:alnum:]][0-9A-Za-z]Matches any alphanumeric character 0–9, A–Z, or a–z
[[:alpha:]][A-Za-z]Matches any alphabetical character, either upper or lower case
[[:blank:]][\t ]Matches a space or Tab character
[[:digit:]][0-9]Matches a numerical digit from 0 through 9
[[:graph:]][[:alnum:][:punct:]]Visible characters (not space)
[[:lower:]][a-z]Matches any lowercase alphabetical character a–z
[[:print:]][ -~] == [ [:graph:]]Matches any printable character
[[:punct:]][!"#$%&’()*+,-./:;<=>?@[]^_{}~]`

Posix BRE Special Character Classes · continued

ClassSame asDescription
[[:space:]][\t\n\v\f\r ]Matches any whitespace character: space, Tab, NL(newline), FF (formfeed), VT (vertical tab), CR (carriage return)
[[:upper:]][A-Z]Matches any uppercase alphabetical character A–Z
[[:word:]][0-9A-Za-z_]Matches all world characters
[[:xdigit:]][0-9A-Fa-f]Matches all hexadecimal digits
[[:<:]][\b(?=\w)]Matches start of word
[[:>:]][\b(?<=\w)]Matches end of word
[[:ascii:]][\x00-\x7F]ASCII codes 0-127
[[:cntrl:]][\x00-\x1F\x7F]Control characters

Quantifiers

?Match an Element Zero or One Time
*Match an Element Zero or More Times
+Match an Element One or More Times
[0-9]+Any digit from 0-9 must appear 1 or more times.
{}Match an Element a Specific Number of Times
a{m}The character a must appear exactly m times.
a{m,n}The character a must appear at least m times, but no more than n times.
a{m,}The character a must appear m or more times.
a*Greedy quantifier

Quantifiers · continued

?Match an Element Zero or One Time
a*?Lazy quantifier
a*+Possessive quantifier
{,n}Match the preceding element if it occurs no more than m times.

Quantifiers

💡 Common Meta-ch­ara­cters ^ ( { | * < $ ) ? > . + [ \ Escape these special characters with \

Groups and ranges

.Any character except new line (\n)
(a|b)a or b
(...)Group
(?:...)Passive (non-c­apt­uring) group
[abc]Range (a or b or c)
[^abc]Not (a or b or c)
[a-q]Lower case letter from a to q
[A-Q]Upper case letter from A to Q
[0-7]Digit from 0 to 7

Special Characters

\nNewline
\rCarriage return
\tHorizontal Tab
\vVertical Tab
\fForm feed
\xxxOctal character xxx
\xhhHex character hh

Pattern Modifiers

gGlobal match
i *Case-i­nse­nsitive
m *Multiple lines
s *Treat string as single line
x *Allow comments and whitespace in pattern
e *Evaluate replac­ement
U *Ungreedy pattern

Escape sequences

\Escape following character
\QBegin literal sequence
\EEnd literal sequence

💡 What is Escaping?

Escaping is a method of treating characters with special meanings in regular expressions literally rather than as special characters.

Assertions

?=Lookahead assertion
?!Negative lookahead
?<=Lookbehind assertion
?!= or ?<!Negative lookbehind
?>Once-only Subexp­ression
?()Condition [if then]
?()|Condition [if then else]
?#Comment

String replacement

$nnth non-pa­ssive group
$2"­xyz­" in /^(abc­(xy­z))$/
$1"­xyz­" in /^(?:a­bc)­(xyz)$/
`$``Before matched string
$'After matched string
$+Last matched string
$&Entire matched string