# Shell Reference

Quick reference for common shell stuff


# Change directory colour output in ls

Create a file with the following contents at ~/.dircolors for Ubuntu

DIR 36

# Useful Bits

# Get name of script

NameAndPath=${BASH_SOURCE}
NameOnly=$(basename ${BASH_SOURCE})

# Date

date +%Y
2020

date +%Y/%m/%d
2020/04/20

date -d "yesterday" +%Y/%m/%d
2020/04/19

date -d "1 day ago" +%Y/%m/%d
2020/04/19

date -d "2020/04/18 + 1 day" +%Y/%m/%d
2020/04/19

# Check if File/Folder Exists

The [] brackets is a shortcut for the test command.

if [ -d /path/to/folder ]; then
  echo "Folder exists"
fi

[ -d /path/to/folder ] && echo "Folder Exists" || "Folder doesn't exist"

if [ -f /path/to/file ]; then
  echo "File exists"
fi
if [ ! -f /path/to/file ]; then
  echo "File doesn't exist"
fi
if [ -x /path/to/file ] ; then
  echo "File exists and can be executed"
fi

# String Test

if [ -z "${VAR}"]; then
  echo "VAR is null"
fi

VAR="Value"
if [ -n "${VAR}"]; then
  echo "VAR is a string"
fi

if [ "${VAR}" = "Value" ]; then
  echo "VAR matches Value"
fi

# Check if file exists and can be executed

test -x /path/to/file
if [ "$?" -eq 0 ]; then
  echo "File can be executed"
fi

#is the same as

test -x /path/to/file
[ "$?" -eq 0 ] && echo "File can be executed"

#is the same as

test -x /path/to/file && echo "File can be executed"

#is the same as

[ -x /path/to/file ] && echo "File can be executed"

# Directly check return code

if command params; then
  echo "good"
else
  echo "bad"
fi

# Redirect all output

This redirects both stdout and errors

echo "Can't see this" >/dev/null 2>&1
echo "Or simpler if your shell supports it" &>/dev/null

# To Lowercase

#!/bin/bash
NEWVARIABLE="${OLDVARIABLE,,}" 

# Check if root

#!/bin/bash
if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit 1
fi

# Write multi-line string to file

cat << EOFF > /path/to/file
This text
will be written
to /path/to/file
  as is.
EOFF

# ls without colour

Add a \ to the front to get rid of aliasing, e.g.

\ls -lah

# Find Open Files by Size

lsof 2>/dev/null| grep REG | awk '{ print $1, "\t", $7=$7/1048576 "M", "\t", $9 }' | sort -ht ' ' -k 2 | column -s ' ' -t

# Sorting

Sort by a different column and use human readable values such as M/G for size or m/h/d for time

sort -h -k <column num>

# Find

# Find old files and perform an action

Looks for things in the path older than 30 days and runs rm on them.
Add -type f for files only, or -name '*.ext' for specific files.

find /path/to/folder/ -mtime 30 -exec rm {} \;

# find files and perform an action on the file name

$1 will be substituted with the found file.

find /path/to/haystack/ -name "file_names*" -exec bash -c 'grep needle $1 | grep another_needle >> ~/output.log' _ {} \;

# Shortcuts

Shortcut Function
ctrl+w Delete word left of cursor
ctrl+u Delete everything before cursor
ctrl+a Move cursor to beginning of line
alt+f Move cursor to the right by one word
alt+b Move the cursor to the left by one word
ctrl+d Delete a character (backspace) or disconnect from session if nothing to delete
ctrl+r Search command history

Reference (opens new window)

# Brackets

## Arithmetic expansion
$(())

echo $((RANDOM%60+1))
31

## Parameter expansion
${}

## Command substitution
$()

# Parameter Expansion Shortcuts

var="Hello World"
# Lower Case
echo ${var,,}
> hello world

var="/path/to/filename.ext"
# Extension
echo ${var##*.}
> .ext

# Filename
echo ${var%.*}
> filename

# Path
echo ${var%/*}
> /path/to

# Functions

functionName() {
  firstParam=$1
  echo "First param is ${firstParam}"
}

functionName "test"
> First param is test

# Loops

# Simple for-loop in CLI

for i in {1..5}; do echo $i; done
1
2
3
4
5

# Loop to a Variable

eval is required here, otherwise the variable is not parsed.

NUMBER=5
for i in $(eval echo "{1..${NUMBER}}"); do echo ${i}; done
1
2
3
4
5

# Loop over a multi-line variable

#!/bin/bash
IFS=$'\n\t'
MULTILINEVAR=$(ls -1 /)
for item in $MULTILINEVAR; do
  echo $item
done

# Loop over lines in a file

while read line; do
  echo ${line}
done < /path/to/file

# Loop over pipe input

grep -oE "needle" /path/to/haystack | while read line; do echo "Found ${line}"; done

# Input Prompt

-p - Append text before input prompt
-s - Hide input text such as passwords

read -p "Username: " USERNAME
read -sp "Password: " PASSWORD
echo "Username is ${USERNAME} and password is ${PASSWORD}"

# Script Parameter Parsing

while getopts ":hr:" opt; do
  case ${opt} in
    h )
      echo "option -h"
      exit 0
      ;;
    r )
      echo "option -r with required parameter"
      rVAR=${OPTARG}
      ;;
    : )
      echo "Required paramter is missing for -${OPTARG}" 1>&2
      exit 1
      ;;
    \? )
      echo "-${OPTARG} is not a valid option" 1>&2
      exit 1
      ;;
    * )
      echo "Catch-all option"
      exit 1
      ;;
  esac
done
shift $((OPTIND -1))

Cheat sheet (opens new window)

Obselete syntax (opens new window)

Bash Hackers (opens new window)

Positional parameters $@ (opens new window)

Last Updated: 2022/11/27 19:17+00:00