Scripts are used to automate tasks and provide human-readable and portable way to do things.
Basics
-
Executable scripts are typically expected to have
.sh
extensions as well as executable bit true which can be checked viaif [[ -f path && -x path ]]; then echo executable; fi
and, if need be, set viachmod +x path
- First line of file should contain information what should be used to execute script, for bash you would
expect first line of script to be
#!/usr/bin/env bash
(variant used in past -#!/bin/bash
- is not always present or bash) - Double quote symbol (
"
) should be used for passing parameters - Single quote symbol (
'
) should be used for passing string literals
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 useDeclaring 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
-
Accessing item under specific index (in this example, second item - first item is under index 0)
echo "${array_var[1]}"
-
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)
One-liner:for i in "${array_var[@]}" do echo "$i" done
for i in "${array_var[@]}"; do echo "$i"; done
-
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 conditionGeneral 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 statementGeneral 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
-
Checking is value of $foo is equal to
123
if [[ $foo == 123 ]]; then echo equal; fi
Checking is value of $foo is equal to123
- integers onlyif [ $foo -eq 123 ]; then echo equal; fi
Checking is value of $foo is equal toitem1 item2 item3
if [[ $foo == 'item1 item2 item3' ]]; then echo equal; fi
-
Checking is value of $foo is less than
123
if [[ $foo < 123 ]]; then echo equal; fi
Checking is value of $foo is less than123
- only integersif [ $foo -lt 123 ]; then echo equal; fi
-
Checking is value of $foo is greater than
123
if [[ $foo > 123 ]]; then echo equal; fi
Checking is value of $foo is greater than123
- only integersif [ $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