You are on page 1of 5

DEVHINTS.

IO Edit

Bash scripting cheatsheet


Introduction Example Variables

This is a quick reference to getting started with #!/usr/bin/env bash name="John"


echo $name # see below
Bash scripting.
name="John" echo "$name"
echo "Hello $name!" echo "${name}!"
Learn bash in y minutes
(learnxinyminutes.com)
Generally quote your variables unless they contain
String quotes wildcards to expand or command fragments.
Bash Guide
(mywiki.wooledge.org)
name="John"
wildcard="*.txt"
echo "Hi $name" #=> Hi John
Bash Hackers Wiki option="iv"
echo 'Hi $name' #=> Hi $name
(wiki.bash-hackers.org) cp -$options $wildcard /tmp

Conditional execution Shell execution Functions

git commit && git push echo "I'm in $(pwd)"


get_name() {
git commit || echo "Commit failed" echo "I'm in `pwd`" # obsolescent
echo "John"
# Same
}

Conditionals See Command substitution


echo "You are $(get_name)"

if [[ -z "$string" ]]; then See: Functions


echo "String is empty" Strict mode
elif [[ -n "$string" ]]; then
echo "String is not empty"
set -euo pipefail Brace expansion
fi
IFS=$'\n\t'

echo {A,B}.js
See: Conditionals
See: Unofficial bash strict mode
{A,B} Same as A B

{A,B}.js Same as A.js B.js

{1..5} Same as 1 2 3 4 5

See: Brace expansion

# Parameter expansions
Basics Substitution Comments

name="John" ${foo%suffix} Remove suffix # Single line comment


echo "${name}"
echo "${name/J/j}" #=> "john" (substitution) ${foo#prefix} Remove prefix
: '
echo "${name:0:2}" #=> "Jo" (slicing)
echo "${name::2}" #=> "Jo" (slicing) ${foo%%suffix} Remove long suffix This is a
multi line
echo "${name::-1}" #=> "Joh" (slicing)
echo "${name:(-1)}" #=> "n" (slicing from right ${foo/%suffix} Remove long suffix comment
'
echo "${name:(-2):1}" #=> "h" (slicing from right
echo "${food:-Cake}" #=> $food or "Cake" ${foo##prefix} Remove long prefix

${foo/#prefix} Remove long prefix Substrings


length=2 ${foo/from/to} Replace first match
echo "${name:0:length}" #=> "Jo" ${foo:0:3} Substring (position, length)
${foo//from/to} Replace all
${foo:(-3):3} Substring from the right
See: Parameter expansion
${foo/%from/to} Replace suffix

str="/path/to/foo.cpp" ${foo/#from/to} Replace prefix Length


echo "${str%.cpp}" # /path/to/foo
echo "${str%.cpp}.o" # /path/to/foo.o ${#foo} Length of $foo
echo "${str%/*}" # /path/to Manipulation
echo "${str##*.}" # cpp (extension) Default values
echo "${str##*/}" # foo.cpp (basepath) str="HELLO WORLD!"
echo "${str,}" #=> "hELLO WORLD!" (lowercase 1s
${foo:-val} $foo, or val if unset (or null)
echo "${str#*/}" # path/to/foo.cpp echo "${str,,}" #=> "hello world!" (all lowercas
echo "${str##*/}" # foo.cpp
str="hello world!"
${foo:=val} Set $foo to val if unset (or null)

echo "${str/foo/bar}" # /path/to/bar.cpp echo "${str^}" #=> "Hello world!" (uppercase 1s


${foo:+val} val if $foo is set (and not null)
echo "${str^^}" #=> "HELLO WORLD!" (all uppercas

str="Hello world" ${foo:?message} Show error message and exit if


echo "${str:6:5}" # "world" $foo is unset (or null)
echo "${str: -5:5}" # "world"

Omitting the : removes the (non)nullity checks, e.g.


src="/path/to/foo.cpp" ${foo-val} expands to val if unset otherwise $foo.
base=${src##*/} #=> "foo.cpp" (basepath)
dir=${src%$base} #=> "/path/to/" (dirpath)
# Loops
Basic for loop C-like for loop Ranges

for i in /etc/rc.*; do for ((i = 0 ; i < 100 ; i++)); do for i in {1..5}; do


echo "$i" echo "$i" echo "Welcome $i"
done done done

With step size

Reading lines Forever


for i in {5..50..5}; do
echo "Welcome $i"
while read -r line; do while true; do done
echo "$line" ···
done <file.txt done

# Functions
Defining functions Returning values Raising errors

myfunc() { myfunc() { myfunc() {


echo "hello $1" local myresult='some value' return 1
} echo "$myresult" }
}

# Same as above (alternate syntax) if myfunc; then


function myfunc() { result=$(myfunc) echo "success"
echo "hello $1" else
} echo "failure"
fi
Arguments
myfunc "John"
$# Number of arguments

$* All positional arguments (as a single word)

$@ All positional arguments (as separate strings)

$1 First argument

$_ Last argument of the previous command

Note: $@ and $* must be quoted in order to perform as


described. Otherwise, they do exactly the same thing
(arguments as separate strings).

See Special parameters.

# Conditionals
Conditions File conditions Example

[[ -e FILE ]] Exists
Note that [[ is actually a command/program that returns # String
if [[ -z "$string" ]]; then
either 0 (true) or 1 (false). Any program that obeys the
[[ -r FILE ]] Readable echo "String is empty"
same logic (like all base utils, such as grep(1) or
elif [[ -n "$string" ]]; then
ping(1)) can be used as condition, see examples. [[ -h FILE ]] Symlink echo "String is not empty"
else
[[ -z STRING ]] Empty string [[ -d FILE ]] Directory echo "This never happens"
fi
[[ -n STRING ]] Not empty string [[ -w FILE ]] Writable

[[ -s FILE ]] Size is > 0 bytes # Combinations


[[ STRING == STRING ]] Equal
if [[ X && Y ]]; then

[[ STRING != STRING ]] Not Equal [[ -f FILE ]] File ...


fi

[[ NUM -eq NUM ]] Equal [[ -x FILE ]] Executable

# Equal
[[ NUM -ne NUM ]] Not equal [[ FILE1 -nt FILE2 ]] 1 is more recent than 2
if [[ "$A" == "$B" ]]

[[ NUM -lt NUM ]] Less than [[ FILE1 -ot FILE2 ]] 2 is more recent than 1
# Regex
[[ NUM -le NUM ]] Less than or equal [[ FILE1 -ef FILE2 ]] Same files if [[ "A" =~ . ]]

[[ NUM -gt NUM ]] Greater than


if (( $a < $b )); then
echo "$a is smaller than $b"
[[ NUM -ge NUM ]] Greater than or equal
fi

[[ STRING =~ STRING ]] Regexp


if [[ -e "file.txt" ]]; then
(( NUM < NUM )) Numeric conditions echo "file exists"
fi
More conditions

[[ -o noclobber ]] If OPTIONNAME is enabled

[[ ! EXPR ]] Not
[[ X && Y ]] And

[[ X || Y ]] Or

# Arrays
Defining arrays Working with arrays

Fruits=('Apple' 'Banana' 'Orange') echo "${Fruits[0]}" # Element #0


echo "${Fruits[-1]}" # Last element
echo "${Fruits[@]}" # All elements, space-separated
Fruits[0]="Apple"
echo "${#Fruits[@]}" # Number of elements
Fruits[1]="Banana"
echo "${#Fruits}" # String length of the 1st element
Fruits[2]="Orange"
echo "${#Fruits[3]}" # String length of the Nth element
echo "${Fruits[@]:3:2}" # Range (from position 3, length 2)
echo "${!Fruits[@]}" # Keys of all elements, space-separated
Operations

Fruits=("${Fruits[@]}" "Watermelon") # Push Iteration


Fruits+=('Watermelon') # Also Push
Fruits=( "${Fruits[@]/Ap*/}" ) # Remove by regex match
for i in "${arrayName[@]}"; do
unset Fruits[2] # Remove one item
echo "$i"
Fruits=("${Fruits[@]}") # Duplicate
done
Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate
lines=(`cat "logfile"`) # Read from file

# Dictionaries
Defining Working with dictionaries Iteration

Iterate over values


declare -A sounds echo "${sounds[dog]}" # Dog's sound
echo "${sounds[@]}" # All values
for val in "${sounds[@]}"; do
echo "${!sounds[@]}" # All keys
sounds[dog]="bark" echo "$val"
echo "${#sounds[@]}" # Number of elements
sounds[cow]="moo" done
unset sounds[dog] # Delete dog
sounds[bird]="tweet"
sounds[wolf]="howl" Iterate over keys

for key in "${!sounds[@]}"; do


Declares sound as a Dictionary object (aka associative echo "$key"
array). done

# Options
Options Glob options

set -o noclobber # Avoid overlay files (echo "hi" > foo) shopt -s nullglob # Non-matching globs are removed ('*.foo' => '')
set -o errexit # Used to exit upon error, avoiding cascading errors shopt -s failglob # Non-matching globs throw errors
set -o pipefail # Unveils hidden failures shopt -s nocaseglob # Case insensitive globs
set -o nounset # Exposes unset variables shopt -s dotglob # Wildcards match dotfiles ("*.sh" => ".foo.sh")
shopt -s globstar # Allow ** for recursive matches ('lib/**/*.rb' => 'lib

Set GLOBIGNORE as a colon-separated list of patterns to be removed from glob matches.

# History
Commands Expansions

history Show history !$ Expand last parameter of most recent command

shopt -s histverify Don’t execute expanded result immediately !* Expand all parameters of most recent command

!-n Expand nth most recent command


Operations
!n Expand nth command in history

!! Execute last command again


!<command> Expand most recent invocation of command <command>

!!:s/<FROM>/<TO>/ Replace first occurrence of <FROM> to <TO> in most recent


command
Slices
!!:gs/<FROM>/<TO>/ Replace all occurrences of <FROM> to <TO> in most recent
command !!:n Expand only nth token from most recent command (command is 0; first
argument is 1)
!$:t Expand only basename from last parameter of most recent
command !^ Expand first argument from most recent command
!$:h Expand only directory from last parameter of most recent !$ Expand last token from most recent command
command
!!:n-m Expand range of tokens from most recent command

!! and !$ can be replaced with any valid expansion.


!!:n-$ Expand nth token to last from most recent command

!! can be replaced with any valid expansion i.e. !cat, !-2, !42, etc.

# Miscellaneous
Numeric calculations Subshells

$((a + 200)) # Add 200 to $a (cd somedir; echo "I'm now in $PWD")
pwd # still in first directory

$(($RANDOM%200)) # Random number 0..199

Redirection
declare -i count # Declare as type integer
count+=1 # Increment
python hello.py > output.txt # stdout to (file)
python hello.py >> output.txt # stdout to (file), append
python hello.py 2> error.log # stderr to (file)
Inspecting commands python hello.py 2>&1 # stderr to stdout
python hello.py 2>/dev/null # stderr to (null)
command -V cd python hello.py >output.txt 2>&1 # stdout and stderr to (file), equiv
#=> "cd is a function/alias/whatever" python hello.py &>/dev/null # stdout and stderr to (null)
echo "$0: warning: too many users" >&2 # print diagnostic message to stder

Trap errors
python hello.py < foo.txt # feed foo.txt to stdin for python
diff <(ls -r) <(ls) # Compare two stdout without files
trap 'echo Error at about $LINENO' ERR

or Case/switch

traperr() { case "$1" in


echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}" start | up)
} vagrant up
;;
set -o errtrace
trap traperr ERR *)
echo "Usage: $0 {start|stop|ssh}"
;;
esac
Source relative

source "${0%/*}/../share/foo.sh"
printf

printf "Hello %s, I'm %s" Sven Olga


Transform strings #=> "Hello Sven, I'm Olga

-c Operations apply to characters not in the given set printf "1 + 1 = %d" 2
#=> "1 + 1 = 2"
-d Delete characters
printf "This is how you print a float: %f" 2
-s Replaces repeated characters with single occurrence #=> "This is how you print a float: 2.000000"

-t Truncates printf '%s\n' '#!/bin/bash' 'echo hello' >file


# format string is applied to each group of arguments
[:upper:] All upper case letters printf '%i+%i=%i\n' 1 2 3 4 5 9

[:lower:] All lower case letters

Directory of script
[:digit:] All digits

[:space:] All whitespace dir=${0%/*}

[:alpha:] All letters

[:alnum:] All letters and digits


Getting options

Example
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in
-V | --version )
echo "Welcome To Devhints" | tr '[:lower:]' '[:upper:]'
echo "$version"
WELCOME TO DEVHINTS
exit
;;
-s | --string )
Heredoc shift; string=$1
;;
-f | --flag )
cat <<END flag=1
hello world ;;
END esac; shift; done
if [[ "$1" == '--' ]]; then shift; fi

Reading input
Special variables
echo -n "Proceed? [y/n]: "
read -r ans $? Exit status of last task
echo "$ans"
$! PID of last background task

$$ PID of shell
$0 Filename of the shell script
The -r option disables a peculiar legacy behavior with backslashes.

$_ Last argument of the previous command


read -n 1 ans # Just one character
Go to previous directory ${PIPESTATUS[n]} return value of piped commands (array)

pwd # /home/user/foo See Special parameters.


cd bar/
pwd # /home/user/foo/bar
cd -
Check for command’s result
pwd # /home/user/foo

if ping -c 1 google.com; then

Grep check echo "It appears you have a working internet connection"
fi

if grep -q 'foo' ~/.bash_history; then


echo "You appear to have typed 'foo' in the past"
fi

# Also see
Bash-hackers wiki (bash-hackers.org)

Shell vars (bash-hackers.org)

Learn bash in y minutes (learnxinyminutes.com)

Bash Guide (mywiki.wooledge.org)

ShellCheck (shellcheck.net)

41 Comments for this cheatsheet. Write yours!

devhints.io / Search 358+ cheatsheets

Other CLI cheatsheets Top cheatsheets

Cron Homebrew Elixir ES2015+


cheatsheet cheatsheet cheatsheet cheatsheet

Over 358 curated cheatsheets, by httpie adb (Android Debug React.js Vimdiff
developers for developers. cheatsheet Bridge) cheatsheet cheatsheet
cheatsheet
Devhints home
Vim Vim scripting
composer Fish shell cheatsheet cheatsheet
cheatsheet cheatsheet

You might also like