Programster's Blog

Tutorials focusing on Linux, programming, and open-source

BASH Cheatsheet

Table of Contents

About

Below are a set of "cheats" specific to programming BASH scripts. Since my default terminal uses BASH, I quite often confuse my commands with what should really be in the Linux CLI Cheatsheet, so if you can't find what your looking for here, please check that out as well.

Cheats

Bash Guard

Inject this into the top of your bash scripts to ensure that the script is running with in bash rather than sh. This is useful because bash and sh often require different syntax. It won't force the user to re-execute the script properly, but just re-execute itself as it was supposed to be done in the first place.

#!/bin/bash
if ! [ -n "$BASH_VERSION" ];then
    echo "this is not bash, calling self with bash....";
    SCRIPT=$(readlink -f "$0")
    /bin/bash $SCRIPT
    exit;
fi

# Put your code here

Stop Script Execution if Any Step Has An Error

The default shell behavior is to ignore errors in scripts. Placing the following line in your script will have the script stop if any step has an error. Read more

set -e

Get Absolute Path of Current Script

When writing scripts, I always like to use absolute references that are relative to the current file. This allows me to call the script from any directory, whilst also allowing me to pass that path to any other script working in any other directory as well. This is the same as using DIR in PHP. I also have a TCL equivalent.

DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )  

This will not work if the last part of the path is a symlink (directory links are okay). If you want to also resolve any links to the script itself, you need a multi-line solution.

This snippet was taken from a Stack Overflow post.

Ensure Running as Root

Inject this into the top of your bash scripts to ensure that the script is running with sudo or root permissions. This is useful if you need to ensure that once a script is started, it is never going to ask for a password on a "sudo" line if you have any.

USER=`whoami`

if [ "$USER" != "root" ]; then
        echo "You need to run me with sudo!"
        exit
fi

# Your script goes here....

Heredoc Write To File

If you need your BASH script to output some code to a file, then you may wish to make use of heredoc

cat << EOF > myScript.php
<?php
echo 'hello world' . PHP_EOL;
echo "Different quotes this time!" . PHP_EOL;
EOF

Load Environment Variables From File

source /path/to/settings/file.sh  

Save Environment Variable To File For Loading Later

echo "export MY_VARIABLE=`echo $MY_VARIABLE`" > my-file.txt

Get Variable From User

echo -n "Enter your ____ and press [ENTER]: "
read MY_VARIABLE
echo $MY_VARIABLE

Ask User For Confirmation

read -p "Are you sure? " -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    # do dangerous stuff
fi

Store Commands In Variable

You can store commands as strings in variables and execute them later. However, to resolve issues with commands that have quotes, and for readability, it is best to use the eval command on that variable when you want to execute it. E.g.

CMD='echo "hello world"'
eval $CMD

Run the script below to demonstrate why you need to use eval

CMD='echo "hello world"'
echo -n "With eval: "
eval $CMD

echo -n "Without eval: "
$CMD

# Output
# With eval: hello world
# Without eval: "hello world"

String Concatenation Example

prefix="MyPrefix_"
DATETIME=`date +%Y_%m_%d_%H:%M:%S`
name="$prefix$DATETIME"
echo $name

Alternatively, in order to stick characters in between the variables, perform the following.

prefix="MyPrefix"
DATETIME=`date +%Y_%m_%d_%H:%M:%S`
name="`echo $prefix`_`echo $DATETIME`"
echo $name

Handling Arguments

The easiest way to explain this is to demonstrate with the following script:

#!/bin/bash

echo "you passed $# arguments to the script"
echo "They are: $@"
echo "The script is called $0 "
echo "the first argument is $1"
echo "the second argument is $2"

Below is the output I got when I ran it on /tmp/script.sh

you passed 0 arguments to the script  
They are:  
The script is called /tmp/script.sh  
the first argument is  
the second argument is  

Ensure Number Of Expected Arguments

EXPECTED_NUM_ARGS=1;

if [ "$#" -ne $EXPECTED_NUM_ARGS ]; then
    echo "Illegal number of aguments"
fi

Propagate Arguments

If you want to just pass all the arguments through to a subscript then use "$@". e.g

#!/bin/bash
/usr/bin/php /path/to/main.php "$@"

Get File MD5

md5sum [filepath]  

Ensure A Directory Exists

DIRECTORY="/my/directory/path"
if ! [ -d $DIRECTORY ]; then
    echo "$DIRECTORY does not exist!"
    exit;
fi

Ensure Running User Has Write Permission for a Directory

if ! [ -w $DIRECTORY ] ; then 
    echo "You need to run this script with a user that has permission to write to $DIRECTORY" ; 
    exit; 
fi

Check If Variable Is Set

If you want to check that a variable has been set and is not an empty string:

if [[ $MY_VARIABLE ]]; then
    echo "MY_VARIABLE is $MY_VARIABLE";
fi

The following should work too:

if [ -n "$MY_VARIABLE" ]; then
    echo "MY_VARIABLE is $MY_VARIABLE";
fi

Check If Variable is Empty

if [ -z "$EMPTY_STRING" ]; then
    echo "That is an empty string";
fi

Check If Variable Matches String

if [ "$MY_VAR" == "something" ]; then
    echo "That is an empty string";
fi

The spacing around == and [ ] as well as the quotation marks around "$MY_VAR" are important!

Switch / Case Statement

Below is an example switch statement stolen from The Geek Stuff.

case "$1" in

1)  echo "Sending SIGHUP signal"
    kill -SIGHUP $2
    ;;
2)  echo  "Sending SIGINT signal"
    kill -SIGINT $2
    ;;
3)  echo  "Sending SIGQUIT signal"
    kill -SIGQUIT $2
    ;;
9) echo  "Sending SIGKILL signal"
   kill -SIGKILL $2
   ;;
*) echo "Signal number $1 is not processed"
   ;;
esac

Lists (Arrays)

You can create an array with one like like so:

MY_ARRAY=("item1" "item2")  

Or you can spread it over multiple lines by continuously appending to the array:

MY_ARRAY=()
MY_ARRAY+=('foo')
MY_ARRAY+=('bar')

If one needs to create a BASH array from a PHP script's output, then one can do something like so:

$options = ['--bob', '--dick', '--harry', '--my multiword option'];
print(implode(PHP_EOL, $options));

... then on the BASH side:

declare -a MY_ARRAY
readarray -t MY_ARRAY <<< $(php dothis --autocomplete-help)

This gracefully handles spaces in the elements.

Variable Variables

I recommend avoiding variable variables, but they can be used in bash like so:

foo="something"
bar="foo"
echo ${!bar} # outputs "something"

Get Password From User

When getting a password from the user, you want to use stars to prevent others from seeing the inputs. However, because this is the case, you need to make sure they have to re-enter the password to ensure that they did not make a spelling mistake. At no point should you echo out the password.

function getPasswordFromUser()
{
    while [ -z "$PASSWORD" ]
    do
        echo "Please enter a password:"
        read -s PASSWORD1
        echo "Please re-enter the password to confirm:"
        read -s PASSWORD2

        if [ "$PASSWORD1" = "$PASSWORD2" ]; then
            PASSWORD=$PASSWORD1
        else
            # Output error message in red
            red='\033[0;31m'
            NC='\033[0m' # No Color
            echo ""
            echo -e "${red}Passwords did not match!${NC}"
        fi
    done
}

# This works because there is no scope in the function
# any variables defined within it are defined outside it
getPasswordFromUser;
echo "your password is $PASSWORD"

This is also a good example of how to use the while loop.

Create Random Directory

The following command will create a randomly named temporary directory in /tmp, and store the name a variable called RANDOM_DIR. You may need this in your scripts if they need to do something like download and then install a deb file.

RANDOM_DIR=`mktemp -d`

Here are some other useful uses of mktemp.

# Dont store the name, just switch 
# to the dir after creating it
cd $(mktemp -d)

# Create a temporary directory with a provided prefix
mktemp -d -t [prefix for directory]

Colors

You can use echo -e to output text with color. However you will need to look up the relevant color codes which can be found here.

For example:

echo -e "Default \e[95mLight magenta"

Add to Cron (crontab)

Often it's necessary for an installation script to install a cron job, such as to run a script on boot. To do this automatically, just use the following code snippet. Make sure to adjust the third line accordingly.

TMP_CRON_FILE="/tmp/cron_file"
crontab -l > $TMP_CRON_FILE
echo "@reboot /bin/bash /path/to/bash/script.sh" >> $TMP_CRON_FILE
crontab $TMP_CRON_FILE
rm $TMP_CRON_FILE

Time

Unix Timestamp

TIMESTAMP=`date +%s`

Date Variable

DATE=`date +%Y_%m_%d`

Time Variable

TIME=`date +%H:%M:%S`

Date-Time Variable

DATETIME=$(date "+%d-%m-%Y %H:%M:%S") # 18-03-2022 13:40:05
DATETIME=`date +%Y_%m_%d_%H:%M:%S` # 2022_03_18_13:41:10

Networking

Automatically Assign Network Interface To Variable

This is a modified version that came from here.

NETWORK_INTERFACE=`ip link | awk -F: '$0 !~ "lo|vir|veth|docker|br-|wl|^[^0-9]"{print $2;getline}'`

Assign Interface's IP to Variable

INTERFACE="enp7s0"
SERVER_IP=$(ip --json addr show $INTERFACE | jq -r '.[0].addr_info[] | select(.family == "inet") | .local')

This does require you to have the jq packgage installed.

Below is an alternative version that is based on servers that have the ifconfig command.

INTERFACE="eth0"
SERVER_IP=$(ifconfig $INTERFACE | grep "inet addr" |  awk '{print $2;}' | cut -d : -f 2)

For OpenVZ you would want to change $OUTBOUND_INTERFACE to be venet0:0.

Assign Internet IP to Variable

The line below will assign your IP as it appears to others on the internet, to a variable.

SERVER_IP=$(curl --silent ifconfig.me)

Make sure you have curl installed.

References

Last updated: 14th January 2025
First published: 16th August 2018

This blog is created by Stuart Page

I'm a freelance web developer and technology consultant based in Surrey, UK, with over 10 years experience in web development, DevOps, Linux Administration, and IT solutions.

Need support with your infrastructure or web services?

Get in touch