Notes from Bash X in Y Minutes
Created: May 17, 2020
echo 'This is the first line'; echo 'This is the second line'
############ Variables
Variable="Some string"
Variable = "Some string" # => returns error "Variable: command not found"
Variable= 'Some string' # => returns error: "Some string: command not found"
echo $Variable # => Some string
echo "$Variable" # => Some string
echo '$Variable' # => $Variable
echo ${Variable} # => Some string
echo ${Variable/Some/A} # => A string
############ Strings
Length=7
echo ${Variable:0:Length} # => Some st
echo ${Variable: -5} # => tring
echo ${#Variable} # => 11
echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"} # => DefaultValueIfFooIsMissingOrEmpty
# This works for null (Foo=) and empty string (Foo=""); zero (Foo=0) returns 0.
# Note that it only returns default value and doesn't change variable value.
############ Array
array0=(one two three four five six)
echo $array0 # => "one"
echo ${array0[0]} # => "one"
echo ${array0[@]} # => "one two three four five six"
echo ${#array0[@]} # => "6"
echo ${#array0[2]} # => "5"
echo ${array0[@]:3:2} # => "four five"
for i in "${array0[@]}"; do # Print all elements. Each of them on new line.
echo "$i"
done
############ Brace Expansion
echo {1..10} # => 1 2 3 4 5 6 7 8 9 10
echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z
############ Built-in variables
echo "Last program's return value: $?"
echo "Script's PID: $$"
echo "Number of arguments passed to script: $#"
echo "All arguments passed to script: $@"
echo "Script's arguments separated into different variables: $1 $2..."
############ Interpolation
echo "I'm in $(pwd)" # execs `pwd` and interpolates output
echo "I'm in $PWD" # interpolates the variable
echo "There are $(ls | wc -l) items here."
echo "There are `ls | wc -l` items here." # backticks cannot be nested
############ Reading Input
echo "What's your name?"
read Name
echo Hello, $Name!
############ if statement
if [ $Name != $USER ]
then
echo "Your name isn't your username"
else
echo "Your name is your username"
fi
# NOTE: if $Name is empty, bash sees the above condition as:
if [ != $USER ]
# which is invalid syntax
# so the "safe" way to use potentially empty variables in bash is:
if [ "$Name" != $USER ] ...
# There is also the `=~` operator, which tests a string against a Regex pattern:
Email=me@example.com
if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]]
then
echo "Valid email!"
fi
############ Conditional Execution
echo "Always executed" || echo "Only executed if first command fails"
echo "Always executed" && echo "Only executed if first command does NOT fail"
# In if statements:
if [ "$Name" == "Steve" ] && [ "$Age" -eq 15 ]
then
echo "This will run if $Name is Steve AND $Age is 15."
fi
if [ "$Name" == "Daniya" ] || [ "$Name" == "Zach" ]
then
echo "This will run if $Name is Daniya OR Zach."
fi
############ Aliases
alias ping='ping -c 5'
\ping 192.168.1.1 # override the alias for normal ping use
alias -p # print all aliases
############ Expressions
echo $(( 10 + 5 )) # => 15
############ cat
Contents=$(cat file.txt)
echo "START OF FILE\n$Contents\nEND OF FILE"
# => START OF FILE
# => [contents of file.txt]
# => END OF FILE
############ Subshells
(echo "First, I'm here: $PWD") && (cd someDir; echo "Then, I'm here: $PWD")
pwd # still in first directorys
############ stdin, stdout, and stderr redirection
cat > hello.py << EOF
#!/usr/bin/env python
from __future__ import print_function
import sys
print("#stdout", file=sys.stdout)
print("#stderr", file=sys.stderr)
for line in sys.stdin:
print(line, file=sys.stdout)
EOF
# Overrite hello.py
# Variables will be expanded if the first "EOF" is not quoted
python hello.py < "input.in" # pass input.in as input to the script
python hello.py > "output.out" # redirect output from the script to output.out
python hello.py 2> "error.err" # redirect error output to error.err
python hello.py > "output-and-error.log" 2>&1
# redirect both output and errors to output-and-error.log
python hello.py > /dev/null 2>&1
# redirect all output and errors to the black hole, /dev/null, i.e., no output
python hello.py >> "output.out" 2>> "error.err" # append errors
# Overwrite output.out, append to error.err, and count lines:
info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err
wc -l output.out error.err
# Overwrite output.out with "#helloworld":
cat > output.out <(echo "#helloworld")
echo "#helloworld" > output.out
echo "#helloworld" | cat > output.out
echo "#helloworld" | tee output.out >/dev/null
############ case
case "$Variable" in
#List patterns for the conditions you want to meet
0) echo "There is a zero.";;
1) echo "There is a one.";;
*) echo "It is not null.";;
esac
############ for
for Variable in {1..3}
do
echo "$Variable"
done
for ((a=1; a <= 3; a++))
do
echo $a
done
for Variable in file1 file2
do
cat "$Variable"
done
# This will run the command `cat` on file1 and file2
for Output in $(ls)
do
cat "$Output"
done
############ while
while [ true ]
do
echo "loop body here..."
break
done
############ function
function foo ()
{
echo "Arguments work just like script arguments: $@"
echo "And: $1 $2..."
echo "This is a function"
return 0
}
foo arg1 arg2
foo "My name is" $Name
bar ()
{
echo "Another way to declare functions!"
return 0
}
bar
############ Text operations
# report or omit repeated lines, with -d it reports them
uniq -d file.txt
# prints only the first column before the ',' character
cut -d ',' -f 1 file.txt
# replaces every occurrence of 'okay' with 'great' in file.txt
# (regex compatible)
sed -i 's/okay/great/g' file.txt
# The example prints lines which begin with "foo" and end in "bar"
grep "^foo.*bar$" file.txt
# pass the option "-c" to instead print the number of lines matching the regex
grep -c "^foo.*bar$" file.txt
grep -r "^foo.*bar$" someDir/ # recursively `grep`
grep -n "^foo.*bar$" file.txt # give line numbers
grep -rI "^foo.*bar$" someDir/ # recursively `grep`, but ignore binary files
# perform the same initial search, but filter out the lines containing "baz"
grep "^foo.*bar$" file.txt | grep -v "baz"
# if you literally want to search for the string,
# and not the regex, use fgrep (or grep -F)
fgrep "foobar" file.txt
############ Handling signals
# The `trap` command allows you to execute a command whenever your script
# receives a signal. Here, `trap` will execute `rm` if it receives any of the
# three listed signals.
trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM
############ Array
############ Array