• Root/
  • Linux/
  • Scripting
  • Scripts are used to automate tasks and provide human-readable and portable way to do things.

    Basics

    Streams

    It's recommended to use streams instead of temporary files (this allows skipping disk wear and time lost on write then read
    | pipe standard output of previous command to next one
    > redirects standard output to specified path (overwrites content)
    >> redirects standard output to specified path (appends to file's content)
    < take input from specified file
    2>&1 redirects standard error to where standard output goes - portable, recommended method of processing standard error
    2>/dev/null redirects standard error to special null device (to ignore it)
    &> redirects standard output and error to specified path (overwrites content) - non portable,not recommended
    &>> redirects standard output and error to specified path (appends to file's content) - not portable, not recommended

    Variables

    Variables can be used to store values for later use

    Declaring variables

    declare foo="item1 item2 item3" Alternative foo="item1 item2 item3"

    Checking state of variable foo

    if [ ! -v foo ]
    then
    	echo "Variable foo was not set"
    elif [ -z "$foo" ]
    then
    	echo "Variable foo is set to an empty string"
    else
    	echo "Variable foo is set"
    fi

    Using variables

    echo "${foo}" Passing to function (example read_var displays value of variable)
    function read_var() {
    	for i in "$@"
    	do
    		echo "$i"
    	done
    }
    declare foo=("item1" "item2" "item3")
    read_var "${foo}"
    

    Arrays

    Declaring arrays

    declare -a array_var=("item1" "item2" "item3") Alternative array_var=("item1" "item2" "item3")

    Checking size of array

    echo "${#array_var[@]}"

    Using arrays

    1. Accessing item under specific index (in this example, second item - first item is under index 0) echo "${array_var[1]}"
    2. Safely iterating over elements of arrays (double quotes around variable name block are not optional - without them, for will split on whitespaces in array elements)
      for i in "${array_var[@]}"
      do
          echo "$i"
      done
      One-liner: for i in "${array_var[@]}"; do echo "$i"; done
    3. Passing arrays to function (example iterate_over_array iterates over array elements)
      function iterate_over_array() {
      	for i in "$@"
      	do
      		echo "$i"
      	done
      }
      declare -a array_var=("item1" "item2" "item3")
      iterate_over_array "${array_var[@]}"
      

    Conditional statements

    Allows matching actions to condition

    General syntax

    if condition1
    then
    	statements1
    elif condition2
    then
    	statements2
    else
    	fallbackStatements
    fi
    
    Single line syntax: if condition1; then statements1; elif condition2; then statements2; else fallbackStatements; fi

    Examples

    if [[ $foo > 123 ]]
    then
    	echo "$foo is more than 123"
    elif [[ $foo = 123 ]]
    then
    	echo "$foo is 123"
    else
    	echo "$foo is not 123 or greater number"
    fi
    
    Single condition check if [[ $foo > 123 ]]; then echo "$foo is more than 123"; fi

    Case statement

    Allows multi-pattern conditional statement

    General syntax

    case expression_or_variable in
    pattern1)
    	statements1
    	;;
    pattern2)
    	statements2
    	;;
    patternX)
    	statementsX
    	;;
    *)
    	fallbackStatements
    	;;
    esac
    
    Single line general syntax: case expression_or_variable in pattern1) statements1 ;; pattern2) statements2 ;; patternX) statementsX ;; *) fallbackStatements ;; esac

    Example

    case $foo in
    123)
    	echo "$foo matches pattern 123"
    	;;
    100 | "a b")
    	echo "$foo matches pattern 100 or \"a b\""
    	;;
    1?3)
    	echo "$foo matches pattern 1?3"
    	;;
    1*3)
    	echo "$foo matches pattern 1*3"
    	;;
    *)
    	echo "$foo does not match other patterns"
    	;;
    esac
    

    Comparison

    1. Checking is value of $foo is equal to 123 if [[ $foo == 123 ]]; then echo equal; fi Checking is value of $foo is equal to 123 - integers only if [ $foo -eq 123 ]; then echo equal; fi Checking is value of $foo is equal to item1 item2 item3 if [[ $foo == 'item1 item2 item3' ]]; then echo equal; fi
    2. Checking is value of $foo is less than 123 if [[ $foo < 123 ]]; then echo equal; fi Checking is value of $foo is less than 123 - only integers if [ $foo -lt 123 ]; then echo equal; fi
    3. Checking is value of $foo is greater than 123 if [[ $foo > 123 ]]; then echo equal; fi Checking is value of $foo is greater than 123 - only integers if [ $foo -gt 123 ]; then echo equal; fi

    shellcheck

    Tool useful for script syntax and logic verification. Usage:

    shellcheck path_to_script_file

    This isn't antivirus or execution safety checker. It will not complain if script aim to erase all data with no way to recover it. It just provides hints on what could be done to improve likelihood of successful execution of script based on common errors and bad practices.

    Last update: 2024-06-26