Bash Cheat Sheet Quick Reference
A concise guide featuring essential Bash commands and syntax for beginners and advanced users alike, helping you efficiently navigate and manage tasks in the terminal.
Getting Started
greet.sh
#!/bin/bash
GREETING="universe"
echo "Greetings, $GREETING!" # => Greetings, universe!
Run the script:
$ bash greet.sh
Variables
USER="Alice"
echo ${USER} # => Alice (Variables)
echo $USER # => Alice (Variables)
echo "$USER" # => Alice (Variables)
echo '$USER' # => $USER (Exact string)
echo "${USER}!" # => Alice! (Variables)
USER = "Alice" # => Error (about space)
Arguments
$1 … $9 Argument 1 ... 9
$0 The script's name
$1 The first command-line argument
${10} The tenth positional parameter
$# Total count of arguments
$$ The current shell's process ID
$* All provided arguments
$@ All arguments, starting from the first one
$- Current shell options
$_ The last argument used in the previous command
See: Special parameters
Functions
retrieve_name() {
echo "Alice"
}
echo "Your name is $(retrieve_name)"
Conditionals
if [[ -z "$text" ]]; then
echo "Text is empty"
elif [[ -n "$text" ]]; then
echo "Text is not empty"
fi
Brace expansion
echo {X,Y}.txt
{X,Y} Expands to X Y
{X,Y}.txt Expands to X.txt Y.txt
{2..6} Expands to 2 3 4 5 6
See: Brace expansion
Shell execution
# => I’m located at /current/path
echo "I’m located at $(PWD)"
# Equivalent to:
echo "I’m located at `pwd`"
See: Command substitution
Bash Parameter expansions
Syntax
${BAR%suffix} Remove the specified suffix
${BAR#prefix} Remove the specified prefix
${BAR%%suffix} Remove the longest matching suffix
${BAR##prefix} Remove the longest matching prefix
${BAR/from/to} Replace the first occurrence of "from" with "to"
${BAR//from/to} Replace all occurrences of "from" with "to"
${BAR/%from/to} Replace the suffix "from" with "to"
${BAR/#from/to} Replace the prefix "from" with "to"
# Substrings
${BAR:0:3} Extract substring (start position, length)
${BAR:(-3):3} Extract substring from the right
# Length
${#BAR} Get the length of $BAR
# Default values
${BAR:-val} Use $BAR, or "val" if $BAR is unset
${BAR:=val} Set $BAR to "val" if it's unset
${BAR:+val} Return "val" if $BAR is set
${BAR:?message} Display "message" and exit if $BAR is unset
Substitution
FILE="/directory/to/example.txt"
echo ${FILE%.txt} # /directory/to/example
echo ${FILE%.txt}.bak # /directory/to/example.bak
echo ${FILE%/*} # /directory/to
echo ${FILE##*.} # txt (file extension)
echo ${FILE##*/} # example.txt (filename)
echo ${FILE#*/} # directory/to/example.txt
echo ${FILE##*/} # example.txt
echo ${FILE/example/sample} # /directory/to/sample.txt
Slicing
person="Alice"
echo ${person} # => Alice
echo ${person:0:3} # => Ali
echo ${person::3} # => Ali
echo ${person::-1} # => Alic
echo ${person:(-1)} # => e
echo ${person:(-2)} # => ce
echo ${person:(-2):2} # => ce
length=3
echo ${person:0:length} # => Ali
See: Parameter expansion
basepath & dirpath
SOURCE="/directory/to/example.txt"
BASENAME=${SOURCE##*/}
echo $BASENAME # => "example.txt"
DIRNAME=${SOURCE%$BASENAME}
echo $DIRNAME # => "/directory/to/"
Transform
TEXT="GOODBYE EARTH!"
echo ${TEXT,} # => gOODBYE EARTH!
echo ${TEXT,,} # => goodbye earth!
TEXT="goodbye earth!"
echo ${TEXT^} # => Goodbye earth!
echo ${TEXT^^} # => GOODBYE EARTH!
ARRAY=(goodbye Earth)
echo "${ARRAY[@],}" # => goodbye earth
echo "${ARRAY[@]^}" # => Goodbye Earth
Bash Arrays
Defining arrays
Fruits=('Grapes' 'Mango' 'Pineapple')
Fruits[0]="Grapes"
Fruits[1]="Mango"
Fruits[2]="Pineapple"
ARRAY1=(bar{1..3}) # => bar1 bar2 bar3
ARRAY2=({X..Z}) # => X Y Z
# Merge => bar1 bar2 bar3 X Y Z
ARRAY3=(${ARRAY1[@]} ${ARRAY2[@]})
# Declare construct
declare -a Numbers=(6 7 8)
Numbers+=(9 10) # Append => 6 7 8 9 10
Indexing
${Fruits[0]} # First element
${Fruits[-1]} # Last element
${Fruits[*]} # All elements (as a single string)
${Fruits[@]} # All elements (as an array)
${#Fruits[@]} # Total number of elements
${#Fruits} # Length of the first element
${#Fruits[2]} # Length of the third element
${Fruits[@]:1:2} # Subarray (from index 1, length 2)
${!Fruits[@]} # Indices of all elements
Iteration
Fruits=('Grapes' 'Mango' 'Pineapple')
for item in "${Fruits[@]}"; do
echo $item
done
# With index
for index in "${!Fruits[@]}"; do
printf "%st%sn" "$index" "${Fruits[$index]}"
done
Operations
Fruits=("${Fruits[@]}" "Kiwi") # Add item
Fruits+=('Kiwi') # Also add item
Fruits=( ${Fruits[@]/Ban*/} ) # Remove by pattern match
unset Fruits[1] # Remove a specific item
Fruits=("${Fruits[@]}") # Copy array
Fruits=("${Fruits[@]}" "${Veggies[@]}") # Merge with another array
lines=(`cat "datafile"`) # Read from a file
Arrays as arguments
function retrieve() {
local -n arrayRef=$1
local index=$2
echo "${arrayRef[$index]}"
}
Fruits=('Grapes' 'Mango' 'Pineapple')
retrieve Fruits 1 # => Mango
Bash Dictionaries
Defining
declare -A animals
animals[cat]="meow"
animals[horse]="neigh"
animals[duck]="quack"
animals[sheep]="baa"
Working with dictionaries
echo ${animals[cat]} # Cat's sound
echo ${animals[@]} # All sounds
echo ${!animals[@]} # All animal names
echo ${#animals[@]} # Total number of entries
unset animals[cat] # Remove cat
Iteration
for sound in "${animals[@]}"; do
echo $sound
done
for animal in "${!animals[@]}"; do
echo $animal
done
Bash Conditionals
Integer conditions
[[ VALUE -eq VALUE ]] # Equal
[[ VALUE -ne VALUE ]] # Not equal
[[ VALUE -lt VALUE ]] # Less than
[[ VALUE -le VALUE ]] # Less than or equal
[[ VALUE -gt VALUE ]] # Greater than
[[ VALUE -ge VALUE ]] # Greater than or equal
(( VALUE < VALUE )) # Less than
(( VALUE <= VALUE )) # Less than or equal
(( VALUE > VALUE )) # Greater than
(( VALUE >= VALUE )) # Greater than or equal
String conditions
[[ -z TEXT ]] # Empty string
[[ -n TEXT ]] # Not an empty string
[[ TEXT == TEXT ]] # Equal
[[ TEXT = TEXT ]] # Equal (same as above)
[[ TEXT < TEXT ]] # Less than (ASCII comparison)
[[ TEXT > TEXT ]] # Greater than (ASCII comparison)
[[ TEXT != TEXT ]] # Not equal
[[ TEXT =~ REGEX ]] # Regular expression match
Example
# String Check
if [[ -z "$text" ]]; then
echo "Text is empty"
elif [[ -n "$text" ]]; then
echo "Text is not empty"
else
echo "This condition is never met"
fi
# Combinations
if [[ condition1 && condition2 ]]; then
...
fi
# Equal
if [[ "$var1" == "$var2" ]]; then
...
fi
# Regex Match
if [[ '2. hello' =~ ([a-z]+) ]]; then
echo ${BASH_REMATCH[1]}
fi
# Comparison
if (( num1 < num2 )); then
echo "$num1 is less than $num2"
fi
# File Existence
if [[ -e "document.txt" ]]; then
echo "The file exists"
fi
File conditions
[[ -e FILE ]] # File exists
[[ -d FILE ]] # Is a directory
[[ -f FILE ]] # Is a regular file
[[ -h FILE ]] # Is a symbolic link
[[ -s FILE ]] # File size is greater than 0 bytes
[[ -r FILE ]] # File is readable
[[ -w FILE ]] # File is writable
[[ -x FILE ]] # File is executable
[[ f1 -nt f2 ]] # f1 is newer than f2
[[ f1 -ot f2 ]] # f2 is older than f1
[[ f1 -ef f2 ]] # f1 and f2 are the same file
More conditions
[[ -o option ]] # If the specified option is enabled
[[ ! expression ]] # Not (negation)
[[ condition1 && condition2 ]] # And (both conditions must be true)
[[ condition1 || condition2 ]] # Or (at least one condition must be true)
logical and, or
if [ "$1" = 'yes' -a "$2" -gt 0 ]; then
echo "Confirmed"
fi
if [ "$1" = 'no' -o "$2" -lt 0 ]; then
echo "Denied"
fi
Bash Loops
Basic for loop
for file in /var/log/*.log; do
echo $file
done
C-like for loop
for ((j = 0; j < 50; j++)); do
echo $j
done
Ranges
for j in {1..5}; do
echo "Hello $j"
done
# With step size
for j in {10..100..10}; do
echo "Hello $j"
done
Auto increment
count=1
while [[ $count -le 5 ]]; do
echo "Count: $count"
((count++))
done
Auto decrement
count=3
while [[ $count -gt 0 ]]; do
echo "Countdown: $count"
((count--))
done
Continue
for value in $(seq 1 5); do
if [[ $value == 4 ]]; then
continue
fi
echo "$value"
done
Break
for value in $(seq 1 5); do
if [[ $value == 4 ]]; then
# Exit the loop entirely.
break
fi
# This will print 1, 2, and 3
echo "$value"
done
Until
number=0
until [ $number -ge 5 ]; do
echo "$number"
((number++))
done
Forever
while true; do
# Here is some additional code.
done
Forever (shorthand)
while :; do
# Here is some other code.
done
Reading lines
cat data.txt | while read entry; do
echo $entry
done
Bash Functions
Defining functions
greet() {
echo "Hi $1"
}
# Alternate syntax
function greet() {
echo "Hi $1"
}
greet "Alice"
Returning values
calculate() {
local output='computed result'
echo $output
}
result="$(calculate)"
Raising errors
check_status() {
return 1
}
if check_status; then
echo "Operation succeeded"
else
echo "Operation failed"
fi
Bash Options
Options
# Prevents accidental file overwrite
# (echo "hello" > output)
set -o noclobber
# Exits immediately on any command failure
# to prevent cascading issues
set -o errexit
# Reveals hidden errors in pipelines
set -o pipefail
# Warns on using unset variables
set -o nounset
Glob options
# Removes non-matching patterns
# ('*.bar' => '')
shopt -s nullglob
# Triggers an error on non-matching patterns
shopt -s failglob
# Makes pattern matching case-insensitive
shopt -s nocaseglob
# Wildcards will also match hidden files
# (e.g., "*.txt" => ".hidden.txt")
shopt -s dotglob
# Enables recursive globbing with **
# ('src/**/*.js' => 'src/folder/file.js')
shopt -s globstar
Bash History
Commands
history # Display command history
sudo !! # Re-run the last command with elevated permissions
shopt -s histverify # Enable confirmation before executing expanded history commands
Expansions
!$ # Use the final argument from the last command
!* # Use all arguments from the last command
!-n # Recall the nth previous command
!n # Recall the command at position n in history
!<command> # Run the last instance of the specified command
Operations
!! # Run the previous command again
!!:s/<FROM>/<TO>/ # Substitute the first <FROM> with <TO> in the last command
!!:gs/<FROM>/<TO>/ # Replace all <FROM> occurrences with <TO> in the last command
!$:t # Get only the basename of the last argument from the last command
!$:h # Get only the directory of the last argument from the last command
!! # Repeats the entire last command
!$ # Expands the last argument of the previous command
Slices
!!:n # Expands only the nth token from the most recent command (command is 0; first argument is 1)
!^ # Expands the first argument from the most recent command
!$ # Expands the last token from the most recent command
!!:n-m # Expands a range of tokens from the most recent command (from nth to mth)
!!:n-$ # Expands from the nth token to the last token of the most recent command
!cat # Repeats the most recent invocation of the `cat` command
!-2 # Expands to the command executed two commands ago
!42 # Expands to the command with history number 42
Miscellaneous
Numeric calculations
$((a + 200)) # Adds 200 to the value of variable 'a'
$(($RANDOM % 200)) # Generates a random number between 0 and 199
Subshells
(cd somedir; echo "I'm now in $PWD") # Changes to 'somedir' temporarily and prints the current directory
pwd # Still shows the original directory
Inspecting commands
command -V cd # Check the type of 'cd' (function, alias, etc.)
#=> "cd is a function/alias/whatever" # Displays the type of the command
Redirection
python hello.py > output.txt # Redirect standard output to output.txt
python hello.py >> output.txt # Append standard output to output.txt
python hello.py 2> error.log # Redirect standard error to error.log
python hello.py 2>&1 # Merge standard error with standard output
python hello.py 2>/dev/null # Discard standard error output
python hello.py &>/dev/null # Discard both standard output and standard error
python hello.py < foo.txt # Provide foo.txt as standard input to python
Source relative
source "${0%/*}/../share/bar.sh"
Directory of script
DIR="${0%/*}" # Extracts the directory path of the current script
Case/switch
case "$1" in
start | up)
vagrant up
;;
*)
echo "Usage: $0 {start|stop|ssh}"
;;
esac
Trap errors
# Trap errors and display the line number where the error occurred
trap 'echo Error at line $LINENO' ERR
# Function to handle errors with specific details
traperr() {
echo "ERROR: ${BASH_SOURCE[1]} at line ${BASH_LINENO[0]}"
}
# Enable error tracing
set -o errtrace
trap traperr ERR
printf
printf "Hello %s, I'm %s" Sven Olga
# => "Hello Sven, I'm Olga"
printf "1 + 1 = %d" 2
# => "1 + 1 = 2"
printf "Print a float: %f" 2
# => "Print a float: 2.000000"
Getting options
while [[ "$1" =~ ^- && "$1" != "--" ]]; do
case $1 in
-V | --version)
echo "$version"
exit
;;
-s | --string)
shift
string="$1"
;;
-f | --flag)
flag=1
;;
esac
shift
done
if [[ "$1" == '--' ]]; then
shift
fi
Check for command's result
if ping -c 1 google.com > /dev/null 2>&1; then
echo "It seems you have a working internet connection."
fi
Grep check
if grep -q 'foo' ~/.bash_history; then
echo "It seems you've typed 'foo' in the past."
fi
Special variables
$? # Exit status of the last executed command
$! # Process ID (PID) of the most recently executed background task
$$ # Process ID (PID) of the current shell
$0 # Name of the shell script being executed
See: Special parameters.
Backslash escapes
\! # Exclamation mark
\" # Double quote
\# # Hash (used for comments)
\& # Ampersand (used for background processes)
\' # Single quote
\( # Opening parenthesis
\) # Closing parenthesis
\, # Comma
\; # Semicolon (used to separate commands)
\< # Less than (input redirection)
\> # Greater than (output redirection)
\[ # Opening square bracket (used for test commands)
\| # Pipe (used to pass output from one command to another)
\\ # Backslash (used for escaping characters)
\] # Closing square bracket
\^ # Caret (used for bitwise XOR or to denote the start of a line in regex)
\{ # Opening curly brace
\} # Closing curly brace
\` # Backtick (used for command substitution)
\$ # Dollar sign (used for variable expansion)
\* # Asterisk (used as a wildcard)
\? # Question mark (used as a single-character wildcard)
Heredoc
command << EOF
line 1
line 2
line 3
EOF
Go to previous directory
# Print the current working directory
pwd # Outputs: /home/user/foo
# Change directory to 'bar'
cd bar/
# Print the current working directory again
pwd # Outputs: /home/user/foo/bar
# Change back to the previous directory
cd -
# Print the current working directory to confirm the change
pwd # Outputs: /home/user/foo
Reading input
# Prompt the user for input without a newline
echo -n "Proceed? [y/n]: "
# Read the user's response into the variable 'ans'
read ans
# Print the user's response
echo $ans
# Read a single character from user input and store it in 'ans'
read -n 1 ans # Just one character
Conditional execution
# Commit changes to the local Git repository and push them to the remote repository
git commit && git push
# If the commit fails, print a message indicating the failure
git commit || echo "Commit failed"
Strict mode
#!/bin/bash
# Enable strict mode
set -o errexit # Exit immediately if a command exits with a non-zero status
set -o nounset # Treat unset variables as an error when substituting
set -o pipefail # Return the exit status of the last command in the pipeline that failed
# Example function
example_function() {
local name=$1 # Use a local variable to prevent accidental modification of global variables
echo "Hello, $name!"
}
# Main script
example_function "World" # Call the function with an argument
# Demonstration of strict mode
# Uncomment the lines below to see strict mode in action
# unset foo # Uncommenting this will cause an error due to nounset
# echo $foo # This will not execute if 'foo' is unset
# command_that_fails # Uncommenting this will cause the script to exit immediately due to errexit
Optional arguments
#!/bin/bash
# Initialize an array with command-line arguments
args=("$@") # Store all command-line arguments into the 'args' array
# Append additional elements to the array
args+=(foo) # Add 'foo' to the array
args+=(bar) # Add 'bar' to the array
# Print all elements of the array
echo "Array elements: ${args[@]}" # Output the complete array
Array elements: arg1 arg2 foo bar
Comments