My Shell Guide
In this blog post, we will cover some essential aspects of the Bash shell, including basic commands, conditional statements, loops, and special variables. This will serve as a handy reference for those who might forget certain details or want to learn more about Bash scripting.
Basics of Bash Shell
Shebang
A shebang (#!
) is added at the beginning of a shell script to specify the shell interpreter to use. Common options include sh
or bash
.
#!/bin/sh
#!/bin/bash
Shebangs can also include optional parameters:
#!/bin/sh -x
Even non-shell scripts, such as PHP scripts, can have a shebang:
#!/usr/bin/env php
Variables
In Bash, all variables are treated as strings.
# No space after the variable name or after the equal sign.
a=123
# This command is the same as the one above:
a="123"
# For strings with spaces or special characters that need to be escaped, use quotes
a="I know, I know\nWhat's next?"
To assign a variable to another variable:
# Use quotes
b="$a"
# Combine with other literals
b="a is like: $a"
# In case `a` doesn't have a space around it
b="How many ${a}s do you have again?"
Assigning a variable from command output:
a="Today is $(date +%Y-%d-%m)"
Conditional Statements (if
)
Bash provides several ways to write conditions, including []
, test
, [[]]
, let
, and (())
.
General syntax for an if
statement:
if CONDITION
then
# Do something
fi
# Condition and `then` can be on the same line
if CONDITION ; then
# Do something
fi
# Include an `else` section
if CONDITION ; then
# Do A
else
# Do B
fi
Using []
or test
# Test if $a and 123 are equal
if [ $a = "123" ]
# For bash, you can use:
if [ $a == "123" ]
# `test` is equivalent to `[]`
if test $a = "123"
# Test if $a and 123 are not equal
if [ $a != "123" ]
# Test if $a is an empty string
if [ -z $a ]
# Test if $a is NOT an empty string
if [ -n $a ]
# or
if [ ! -z $a ]
# Numeric comparisons:
# If $a equals $b
if [ $a -eq $b]
# If $a and $b are not equal
if [ $a -ne $b]
# If $a is greater than $b
if [ $a -gt $b]
# If $a is greater or equal to $b
if [ $a -ge $b]
# If $a is less than $b
if [ $a -lt $b]
# If $a is less or equal to $b
if [ $a -le $b]
# Logical operators:
# If $a equals 1 and $b equals 2 (does NOT short-circuit)
if [ $a = 1 -a $b = 2 ]
# or (short-circuits)
if [ $a = 1 ] && [ $b = 2 ]
# If $a equals 1 or $b equals 2 (does NOT short-circuit)
if [ $a = 1 -o $b = 2 ]
# or (short-circuits)
if [ $a = 1 ] || [ $b = 2 ]
# If `$dir` is an existing directory path
if [ -d "$dir"]
# If `$file_path` is not an existing file path
if [ ! -f "$file_path"]
Using [[]]
The [[]]
notation is specific to Bash and ksh and was introduced in Bash version 2.02. It provides more expressive capabilities than []
.
# Use wildcards
if [[ $a = 12* ]] # Matches `123`, `12f2`, `12dsa`, etc.
if [[ $a = 12? ]] # Matches `123`, `12f`, `12w`, etc.
# Use a literal asterisk by quoting it
if [[ $a = "12*" ]] # Matches `12*` only
# Compare using standard math notations
if [[ $a > $b ]]
# Use logical operators inside the brackets (short-circuits)
if [[ $a = 1 && $b = 2 ]]
# or (short-circuits)
if [[ $a = 1 ]] && [[ $a = 2 ]]
Using (())
The (())
notation is for arithmetic calculations, and its result can be used as a logical value for an if
statement.
# Omit the dollar sign for variables and use a more flexible syntax
if ((a==10))
# The single equal sign `=` means assignment here
if ((a=1)) # This will always be true, and $a will become 1
# More complex examples:
if ((a>6 && b<10))
if ((a/3==4))
while
Loops
Understanding conditions for if
statements makes understanding while
loops easy. until
loops are similar to while
loops but run only when the condition is NOT met.
while CONDITION
do
# Repeatedly do something
done
# A simple example
while ((i <= 100))
do
((sum += i))
((i++))
done
# Same thing using until
until ((i > 100))
do
((sum += i))
((i++))
done
# Use `continue` and `break`
until ((i > 100))
do
((sum += i))
((i++))
if ((i==40)) ; then
break
else
continue
fi
done
for
Loops
for
loops in Bash come in two styles: one similar to C/C++, and the other similar to Python. You can also use break
and continue
.
C-style for
loop
for ((i=1; i<=100; i++))
do
((sum += i))
done
Python-style for
loop
# List values
for n in 1 2 3 4 5 6
do
echo $n
((sum+=n))
done
# Can be strings (numbers are also strings)
for str in "a" "b" "c"
do
echo $str
done
# Can be a range
for n in {1..100}
do
((sum+=n))
done
# Or range of characters (in the order of ASCII codes)
for c in {A..z}
do
echo $c # This will include []^_`
done
# Can also use the result of a command
for filename in $(ls *.sh)
do
echo $filename
done
Unix Special Variables
Variable | Description |
---|---|
$0 | The filename of the current script. |
$n | These variables correspond to the arguments with which a script was invoked. Here n is a positive decimal number corresponding to the position of an argument (the first argument is $1 , the second argument is $2 , and so on). |
$# | The number of arguments supplied to a script. |
$* | All the arguments, all double quoted. If a script receives two arguments, $* is equivalent to $1 $2 . |
$@ | All the arguments, all individually double quoted. If a script receives two arguments, $@ is equivalent to $1 $2 . |
$? | The exit status of the last command executed. |
$$ | The process number of the current shell. For shell scripts, this is the process ID under which they are executing. |
$! | The process number of the last background command. |
Snippets
Get the script path:
shell_dir=$(dirname "$0")
Delete a directory if it exists:
if [ -d "$dir" ] ; then
rm -rf "$dir"
fi
Create a directory if it doesn't exist:
if [ ! -d "$dir" ] ; then
mkdir -p "$dir"
fi
In conclusion, this blog post has covered the basics of Bash shell scripting, including variables, conditional statements, loops, and special variables. With this knowledge, you can create powerful and efficient scripts for various tasks. Remember to refer back to this post as a handy reference whenever you need a refresher on Bash shell scripting.