Skip to content

Shell cookbook

Overview

Cookbook on shell script (Mostly for bash shell)

Cookbook

Default shell with shebang

To using the bash as the default shell, configure with shebang at the first line of the script/Makefile.

#!/bin/bash

Define platform type with case-when

Handle different OS with case-when by define from variable name $OSTYPE

case "$OSTYPE" in
    msys*)
        echo "Operation system: Window >"
        declare PY_CMD=python
        declare ACTIVATE_DIR=Scripts
    ;;
    linux*)
        echo "Operation system: Linux >"
        declare PY_CMD=python3
        declare ACTIVATE_DIR=bin
    ;;
    *)
        echo "Not supported for this os: '$OSTYPE'"
    ;;
esac

Check user is root or not

👻 Check user is root or not from Idea from bash exit

Use case: Using for element

if [[ "$(whoami)" != root ]]; then
  echo "Only user root can run this script."
  exit 1
fi

Conditional check

There are a lot of work behind the boolean conditions check with Bash. More idea captured: https://stackoverflow.com/questions/2953646/how-can-i-declare-and-use-boolean-variables-in-a-shell-script Below returned different values.

# Failed
if [[ true &&  true && true &&  false ]];
then echo 1
else echo 2
fi;

# Worked
if true && true && true && false;
then echo 1
else echo 2
fi;

Retries

Replace "command" with your command. This is assuming that "status code=FAIL" means any non-zero return code.

for i in 1 2 3 4 5; do <command> && break || sleep 15; done

Variations: Using the {..} syntax. Works in most shells, but not BusyBox sh:

for i in {1..5}; do command && break || sleep 15; done Using seq and passing along the exit code of the failed command:

Reference: Retry on bash

# Replace "command" with your command. This is assuming that "status code=FAIL" means any non-zero return code.
for i in 1 2 3 4 5; do command && break || sleep 15; done


for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)

# Same as above, but skipping sleep 15 after the final fail. Since it's better to only define the maximum number of loops once, this is achieved by sleeping at the start of the loop if i > 1:
for i in $(seq 1 5); do [ $i -gt 1 ] && sleep 15; command && s=0 && break || s=$?; done; (exit $s)

Reference: https://unix.stackexchange.com/questions/82598/how-do-i-write-a-retry-logic-in-script-to-keep-retrying-to-run-it-upto-5-times

For loop in Bash script

Synponis:

for fold in <Interator>
do
    <Statement>
done

note:

can be in various form

Example

Using array and do echo interator

declare
for fold in <Interator>
do
    <Statement>
done

Note:

[1] the double quotes around "${arr[@]}" are really important.

Based on Gabriel Staples comment [^2] on Jun 14, 2020 at 20:13

Without them, the for loop will break up the array by substrings separated by any spaces within the strings instead of by whole string elements within the array. ie: if you had declare -a arr=("element 1" "element 2" "element 3"), then for i in \({arr[@]} would mistakenly iterate 6 times since each string becomes 2 substrings separated by the space in the string, whereas for i in "\)" would iterate 3 times, correctly, as desired, maintaining each string as a single unit despite having a space in it.

Usage

[1] Removed basket of folder based on condition

[2] Find and search

Alias commad

# Syntax
# $ alias <alias-name>="command to execute in string"

# Example: to authentication Google SDK with ADC method
alias gadc="gcloud auth application-default login"

Load the function as the component

To do this, use the .bashrc for each user

vi ~/.bashrc
source ~/.bashrc

Note: alway add \n at the end of file

Bash: Find

Using to search in the directory tree

Usage:

Delete cache folder from Python

If you using -delete, the error shell find -delete "directory not empty"

find ./ -name '__pycache__' -type d -path 'component/*' -exec rm -r {} +

The true type

# Position syntax
# <command> <search-path> <option>
find ./ -name '__pycache__' -type d -path 'component/*' -exec rm -r {} +

See: https://unix.stackexchange.com/questions/249501/shell-find-delete-directory-not-empty