Bash Scripts

Examples of using Bash in a script



Loop over an array, read in from a file

#!/bin/bash

# A BASH script makes the first command line argument available as $1, the second as $2 and so on.
# The command run, exactly as it was called but without the command line arguments, is stored in $0.
#
# The dirname command returns the directory name part of a filename.
# Note that the directory and/or file do not actually exists; dirname simply strips the last component of a file path.
# For example, "dirname /a/b/c" will echo "/a/b", "dirname ../a/b/c" will echo "../a/b", "dirname ../" will echo "." and so on.
#
# The directory the BASH script is located in can be retrieved using "dirname $0"
#
# Note although the cd command is used, the script will not change directory and any other calls within it are still relative to the current working directory.
#
# This is useful when you need to reference a file that sits next to the script.
cd $(dirname "$0")

# Read in from fileName and store in varName
# IFS is the field separator
IFS=$'\n' read -d '' -r -a varName < ./fileName

# Loop through items in varName
for i in "${varName[@]}"; do
  echo "processing ${i}"

 printf "\n\n\n"

done


Compare two different files

#!/bin/bash

IFS=$'\n' read -d '' -r -a fileAResource < /tmp/fileA-resource

IFS=$'\n' read -d '' -r -a fileBResource < /tmp/fileB-resource-sco

# FILEA_TOTAL_COUNT holds the total number of resource in FILEA
FILEA_TOTAL_COUNT=0
# FILEA_ORPHANED_COUNT holds the number of orphaned resource
FILEA_ORPHANED_COUNT=0
# FILEA_ORPHANED holds the names of the orphaned resource
FILEA_ORPHANED=()

# FILEB_TOTAL_COUNT holds the total number of resource in FILEB
FILEB_TOTAL_COUNT=0
# FILEB_ORPHANED_COUNT holds the number of orphaned resource
FILEB_ORPHANED_COUNT=0
# FILEB_ORPHANED holds the names of the orphaned resource
FILEB_ORPHANED=()

# Loop through items in fileAResource
for i in "${fileAResource[@]}"; do
  EXISTS_IN_FILEB=$(cat /tmp/fileB-resource | grep "$i")

  # If the string is null (empty)
  if [ -z "$EXISTS_IN_FILEB" ]; then
    FILEA_ORPHANED+=("$i")
    ((FILEA_ORPHANED_COUNT++))
  fi

  ((FILEA_TOTAL_COUNT++))
done

# Loop through items in fileBResource
for i in "${fileBResource[@]}"; do
  EXISTS_IN_FILEA=$(cat /tmp/fileA-resource | grep "$i")

  # If the string is null (empty)
  if [ -z "$EXISTS_IN_FILEA" ]; then
    FILEB_ORPHANED+=("$i")
    ((FILEB_ORPHANED_COUNT++))
  fi

  ((FILEB_TOTAL_COUNT++))
done

if [[ $1 == "fileA-debug" ]]; then
  echo "${FILEA_ORPHANED[@]}"
fi

if [[ $1 == "fileB-debug" ]]; then
  echo "${FILEB_ORPHANED[@]}"
fi

echo "There are $FILEA_ORPHANED_COUNT (out of $FILEA_TOTAL_COUNT) orphaned resource (resource that exist in FILEA but not FILEB)"

echo "There are $FILEB_ORPHANED_COUNT (out of $FILEB_TOTAL_COUNT) orphaned resource (resource that exist in FILEB but not FILEA)"


Compare two different resource endpoints

#!/bin/bash

# Set field separator as our commands return each resource on a newline
IFS=$'\n'

TA_RESOURCES=$( // command to get resources // )
TA_RESOURCES=($TA_RESOURCES)

TB_TOKEN=$( // command to get token // )
TB_RESOURCES=$(curl -s -H "Authorization: Bearer $TB_TOKEN" -H "Content-Type: application/json" "$ENDPOINT" | jq -r '.[].name')
TB_RESOURCES=($TB_RESOURCES)


TB_TOTAL=0
TB_ORPHANED_TOTAL=0
TB_NON_ORPHANED_TOTAL=0

TB_ORPHANED=()

TA_TOTAL=0
TA_ORPHANED_TOTAL=0
TA_NON_ORPHANED_TOTAL=0

TA_ORPHANED=()

for i in "${TB_RESOURCES[@]}"; do
  if echo ${TA_RESOURCES[@]} | grep -q -w "$i"; then
    # IS in array
    ((TB_NON_ORPHANED_TOTAL++))
  else
    # IS NOT in array
    TB_ORPHANED+=()
    ((TB_ORPHANED_TOTAL++))
  fi

  ((TB_TOTAL++))
done

for i in "${TA_RESOURCES[@]}"; do
  if echo ${TB_RESOURCES[@]} | grep -q -w "$i"; then
    # IS in array
    ((TA_NON_ORPHANED_TOTAL++))
  else
    # IS NOT in array
    TA_ORPHANED+=()
    ((TA_ORPHANED_TOTAL++))
  fi

  ((TA_TOTAL++))
done

if [[ $1 == "ta-debug" ]]; then
  echo "${TA_ORPHANED[@]}"
fi

if [[ $1 == "tb-debug" ]]; then
  echo "${TB_ORPHANED[@]}"
fi

echo "TB -- (Total: $TB_TOTAL) (Orphaned: $TB_ORPHANED_TOTAL) (Not Orphaned: $TB_NON_ORPHANED_TOTAL)"
echo "TA -- (Total: $TA_TOTAL) (Orphaned: $TA_ORPHANED_TOTAL) (Not Orphaned: $TA_NON_ORPHANED_TOTAL)"
Check example configuration file contains all relevant variables from local configuration file

#!/bin/bash

EXAMPLE_FILE=local.env.example
LOCAL_FILE=local.env

if [[ ! -f "$LOCAL_FILE" ]]; then
    echo "local environment file doesn't exist"
    exit 0
fi

if [[ ! -f "$EXAMPLE_FILE" ]]; then
    echo "example environment file doesn't exist"
    exit 1
fi

LOCAL_CONTENTS=$(cat ./${LOCAL_FILE} | grep export | sed 's/^export //g' | awk -F'=' '{print $1}')
EXAMPLE_CONTENTS=$(cat ./${EXAMPLE_FILE} | grep export | sed 's/^export //g' | awk -F'=' '{print $1}')

ERRS=()

# Process contents of EXAMPLE_CONTENTS, line-by-line.
# IFS is empty as we don't want to separate the contents on each line
while IFS='' read -ra ADDR; do
  for i in "${ADDR[@]}"; do
    # If the env var is commented out, ignore it
    if [ "${i:0:1}" == "#" ]; then
      continue
    fi

    EXISTS_IN_EXAMPLE=$(echo "$EXAMPLE_CONTENTS" | grep "$i")

    # If the string is null (empty)
    if [ -z "$EXISTS_IN_EXAMPLE" ]; then
      ERRS+=("$i")
    fi
  done
done <<< "$LOCAL_CONTENTS"

if [[ ! ${#ERRS[@]} -eq 0 ]]; then
    echo "The following environment variables are defined in $LOCAL_FILE, but not in $EXAMPLE_FILE:"
    echo "${ERRS[@]}"
    exit 1
fi


Rename files

#!/bin/bash

# For every file in the current directory
for file in *; do
        # Ignore files with a .sh extension
        [[ $file == *.sh ]] && continue

        # Use sed/regex to remove everything from '-' to '.' (inclusive) and replace with '.'
        NewName=$(echo ${file} | sed 's/-.*\././')

        # Change spaces to \[space]
        NoSpaces=$(echo ${NewName} | sed 's/ /\\ /g')

        echo "Moving '$file' to $NoSpaces"

        mv "$file" "$NoSpaces"
done


rsync script

#!/bin/bash

# Find running rsync processes that aren't the one we spawn (grep) with this command
RUNNING="$(ps -ef | grep rsync | grep --invert-match 'grep')"

# Only spawn more rsync jobs if there aren't some already running
if [[ -z "$RUNNING" ]]; then
    echo "Running rsync commands"

	rsync -aqz --remove-source-files --no-o --no-g --no-perms /source/files /destination > /dev/null 2>&1 &
else
        echo "Not running rsync commands, there is one already running"
fi


Using command line flags

#!/bin/bash

# Get the directory of the bash script
cd $(dirname $BASH_SOURCE)
DIR=$(pwd)

APP_ONE_ENV=prod
APP_TWO_ENV=lve

# If number of arguments is less than 10, the flags haven't been supplied
if [ $# -lt 10 ]
  then
    echo "usage: ./script.sh -l {login true/false} -e {escalate true/false} -s {resourceid} -j {JIRA ticket} -u {requesting user}"
    exit 1;
fi

if [[ $(appone config show-context) != ${APP_ONE_ENV} ]]; then
  echo "appone not configured for correct environment"
  exit 1
fi

if [[ $(apptwo -c) != ${APP_TWO_ENV} ]]; then
  echo "apptwo not configured for correct environment"
  exit 1
fi

while getopts l:e:s:j:u: flag
do
    case "${flag}" in
        l) login=${OPTARG};;
        e) escalation=${OPTARG};;
        s) resourceid=${OPTARG};;
        j) jiraticket=${OPTARG};;
        u) username=${OPTARG};;
    esac
done

if [ "$login" == "true" ]; then
  # Login to appone
  appone auth login

  # Login to apptwo
  apptwo auth login
fi

STATE=$(appone resource get "$resourceid" -o json | jq .state)

if [ ! "$STATE" == "Deleted" ]; then
    echo "Resource is not in a Deleted state"
    exit 1
fi

if [ "$escalation" == "true" ]; then
  ESCALATION_OUTPUT=$(apptwo escalate)

  echo "$ESCALATION_OUTPUT"
fi



Create a mini-CLI programme

#!/bin/sh

# Get the directory of the bash script
cd $(dirname $BASH_SOURCE)
DIR=$(pwd)

COMMAND=$1
RESOURCE_NAME=$2
VERSION=$3

FILE_CREATE=~/dir/aSubDIR/test-resource.json
FILE_UPDATE=~/dir/aSubDIR/test-resource-update.json

REGEX='help'

# Perform a regex match of the string
if [[ $COMMAND =~ $REGEX ]];
then
  echo "available commands:
    - list
    - listByOwner
    - countByOwner
    - approve {resource} {version}
    - cancel {resource} {version}
    - cancel-termination {resource}
    - create {resource}
    - delete {resource}
    - get {resource}
    - job-status {resource}
    - history {resource}
    - reject {resource} {version}
    - update {resource}
  "
  exit 0;
fi

if [ "$COMMAND" == 'list' ]; then
    # Print executed command to the terminal
	set -x
	cmd resources list
    # Disable printing executed commands to the terminal
	set +x
	exit 0;
fi

if [ "$COMMAND" == 'listByOwner' ]; then
    set -x
	cmd resources list --verbose -o json | jq -r --arg USER "$2" '.[] | select(.createdBy==$USER) | .name'
	set +x
	exit 0;
fi

if [ "$COMMAND" == 'countByOwner' ]; then
    set -x
	cmd resources list --verbose -o json | jq '.[].createdBy' | sort | uniq -c | sort -r
	set +x
	exit 0;
fi

# If number of arguments is less than 2
if [ $# -lt 2 ]
  then
    echo "usage: ./cmd-commands.sh {command} {resource-name} [version]"
    exit 1;
fi


if [ "$COMMAND" == 'approve' ]; then
        # If the string is null (empty)
        if [ -z "$VERSION" ]
                then
                echo "Version not provided"
                exit 1;
        fi
        set -x
        cmd resources approve $RESOURCE_NAME --version $VERSION --reason "An optional reason for why this is approved"
        set +x
        exit 0;
fi

if [ "$COMMAND" == 'cancel' ]; then
        if [ -z "$VERSION" ]
                then
                echo "Version not provided"
                exit 1;
        fi
        set -x
        cmd resources cancel $RESOURCE_NAME --version $VERSION --reason "A valid reason for why the update is being cancelled"
        set +x
        exit 0;
fi

if [ "$COMMAND" = 'cancel-termination' ]; then
	set -x
	cmd resources cancel-termination $RESOURCE_NAME --reason "TEST-1245 cancel termination"
	set +x
	exit 0;
fi


if [ "$COMMAND" == 'create' ]; then
        set -x
        cmd resources create $RESOURCE_NAME -f $FILE_CREATE --reason "TEST-0000 testing new commands"
        set +x
        exit 0;
fi

if [ "$COMMAND" == 'delete' ]; then
        set -x
        cmd resources delete $RESOURCE_NAME --reason "TEST-1234 deleting resource"
        set +x
        exit 0;
fi

if [ "$COMMAND" == 'get' ]; then
        set -x
        cmd resources get $RESOURCE_NAME
        set +x
        exit 0;
fi

if [ "$COMMAND" == 'history' ]; then
        set -x
        cmd resources history $RESOURCE_NAME
        set +x
        exit 0;
fi

if [ "$COMMAND" == 'update' ]; then
        set -x
        cmd resources update $RESOURCE_NAME -f $FILE_UPDATE --reason "TEST-0000 testing new commands - update"
        set +x
        exit 0;
fi