The is a good practise to put hash-band line at the beginning of each script to tell which shell should execute this script
#!/bin/bash
To make file executable use
chmod u+x file_name
Single quotes escape everything inside.
Double quotes don’t escape $
, {}
. But escape ~
(use $HOME
instead).
Every unix command return result code. 0
means success. Other values are error codes.
To finish script execution run
exit exit_code
$?
- exit status for last command
${#var}
- the length of the string in a variable
--
- end of options command.
$(...)
- runs command in subshell (inner variables does not appear in main shell)eval
- gets the string and evaluates it as if you type it in the terminal$0
- script name$1
- get the first param of the script$2
- get the second param of the script$#
- the number of script arguments“$@”
- equivalent to “$1”, “$2”, .., “$N”
(arguments in array)“$*”
- equivalent to “$1 $2 $3… $N”
(arguments in string)$$
- PID
of current process$?
- status of the last command$!
- PID last command while (( $# )); do
echo $1
shift
done
shift
- removes the first argument ($2 => $1, $3 => $2)
shift n
- removes first n argumentsgetopts
- parse script options (like -p). Stops on an argument which does not starts with -.
getopts opt_string var_name
“ab”
will let your script handle an option -a
and/or -b
:
to options that take an argument“a:b”
will let a
take an argument, but not b
OPTARG
- argument of an optionOPTIND
- holds the index of the next argument to be processedgetopts
returns false when no more options are leftgetopts
handles erros for you. If anything goes wrong, the option variable var_name holds “?”
“:bsr”
“?”
will be putted in var_name
OPTARG
“:”
in option var_name
OPTARG
To create variable and assign value to it (do not put space before or after =
)
var_name=var_value
To extract variable value use
$var_name
To assign combo value use the following
greeting=”hello”
user_greeting=”$greeting, $USER”
$x
“$x”
To tell where you variable ends use braces {}
${var_name}
To read a line of input into variable use
read var_name
All variables have attributes. To set attribute use declare.
declare -p var_name
- print attributes for a variable
To set variable as readonly
declare -r const_name=”some value”
To export variable to child process use:
export var_name
declare -x var_name
Note: you can not pass variable from child scirpt to parent. When you pass variable to sub process the attributes of this variables do not get passed.
declare -a var_name
- declares an array variablex[0]=”some”
- assigns value to 0 element of x array${x[0]}
- retrives 0 value from an array${x[@]}
or ${x[*]}
- retrieves all values from an arrayar=(1 2 3 a b c)
- creates array of 6 elements${#var_name[@]}
- gets the array length${!var_name[@]}
- gets all array indices (there can be gaps in the indices)declare -A var_name
- declares dictionaryecho ${array[*]}
- print all elements in arrayvar_name=$(cat <<some_custom_tag
multiline string
some_custom_tag
)
${var:-value}
- will evaluate to “value” if var is empty or unset${var-value}
- will evaluete to “value” if var is unset${var:=value}
- if var was empty or unset, this evaluates to “value” and assigns it to var${var=value}
- if var was unset, this evaluates to value
and assigns it to vardeclare -i var_name
- add integer attribute to a varibaledeclare +i var_name
- removes integer attribute from a variablelet
- C-like syntax for doing calculation
let n=100/2
- sets variable n to integer((..))
- arithmetic expression.
((++x))**
- increment x variable((p=x/100))
(p= $( ls | wc -l )*10)
$((..))
- this is a substitution, not a command
if variable declared as integer:
declare -i x
x=”from max”
echo $x # 0
((..))
can be used in if. In this case: 0
is false
, anything else is true
To debug your bash script put ‘-x’ to shellband
#!/bin/bash -x
To run script in debug mode use
bash -x script_name
To show command only for some lines use
set -x
bash_code_to_debug
set +x
-e - exists script whenever a command faild (but not with if, while, until, | , &&) |
shopt -s nocaseblob
- ignore case with pathname expansionshopt -s extglob
- enable extended pattern matchingshopt -s dotglob
- include hidden files with path name expansionman test
man [
help [[
help test
[ 56 -gt 55 ] && echo true || echo false # true
test 56 -gt 55 && echo $? # 0
Test options:
Expression | Meaning |
---|---|
[[ $str ]] | str is not empty |
[[ -n $str ]] | str is not empty |
[[ -z $str ]] | str is empty |
[[ $str = pattern ]] | checks unix pattern matching |
[[ $str=sometning ]] | always return true. Do not do like this! |
[[ $str = ~sometning ]] | checks regular expression matching |
[[ -e $filename ]] | checks if file exists |
[[ -d $dirname ]] | checks if directory exists |
[[ -s $filename ]] | check if file has size more than 0 |
[[ -[rwx] $filename ]] | check if file is available for read/write/execute |
=
is the same as ==
To compare numbers (only integer supported)
[[ arg1 OP arg2 ]]
- where OP: -eq, -ne, -lt, -gt
The condition syntax
if <condition or command>; then
<code>
elif <condition or command>; then
<code>
else
<code>
fi
!
, &&
, ||
while
- repeats code while test true
while test; do
code to be repeated
done
until
- repeats code while test false
until test; do
code to be repeated
done
for
- assign each word in words to var . Stops when no words are left. Do NOT quote words.
for i in {1..10}; do
echo $i
done
for VAR in WORDS; do
code
done
iterate through files in pwd
for file in *; do
echo $file
done
iterate through files according to template in pwd
for file in *.txt; do
echo $file
done
iterate till max
for (( i=0; i<max; i++ )); do
code
done
$
to get variable value for counter in `seq 1 20`; do
echo $counter
done
for counter in {1..20}; do
echo $counter
done
case
case WORD in
PATTERN1)
code for pattern1;;
PATTERN2)
code for pattern2;;
....
PATTERNNn)
code for pattern n;;
?)
code for not matching pattern
esac
||
and &&
- combines multiple commands depending on their result. Commands are executed in order, they do not use any priorites
[[ $1 ]] || echo “missing argument”
- print error when there is no argument[[ $1 ]] || echo “missing argument” && exit 1
- always exits!!![[ $1 ]] || { echo “missing argument” >&2; exit 1; }
- good way to check input params{ }
- group commands
{ cmd1; cmd2; cmd3 }
echo
- display a line of text
printf
- format and print data
To put argument in printf command use
printf "hello %s, how are you?\n" $USER
To put printf output to a variable use -v option
printf -v var_name “some_str”
read
- reads input into a variable
read x
REPLY
-n
stop read at the new line-N
reads exact number of characters-s
will suspess otput (useful for passwords)-r
dissallow escare sequences, line continuation (best practice to use this option)to read 2 variables at one time:
read var_1 var_2 var_1_value var_2_value
An Introduction to Linux I/O Redirection
0
: Standart Input (stdin)
/dev/stdin
1
: Standart Output (stdout)
/dev/stdout
2
: Standart Error (stderr)
/dev/stderr
/dev/null
- discards all data send to itInput redirection: <
grep milk < shoppingnotes.txt
Output redirection: >
ls > listing.txt
>
- will overwite existing files>>
- appends to the end of a filePipes
ls | grep x
Redirect a specific stream with N>
(where N is the number of stream, 1
is default )
cmd 2>/dev/null
- discards all errorsRedirect to a specific stream with >&N
>&2
- sends output to stderr2>&1
- redirects stderr into stdoutTo redirect all I/O for the whole script use exec (usefull for logging)
exec >logfile 2>errorlog
A command in a pipeline runs in a subshell
declare -i count=0
ls | while read -r; do ((++count)); done # do not increases global count
Examples
command > file
- redirects out of a command to a filecommand > /dev/null
- discards out of a commandcommand 2> file
- redirects standart error stream to a filecommand | tee file
- redirects standart ouput of the command to a file and backward to outputcommand > logfile 2>&1
- sending both error and ouput to a single fileTo define function use
function_name () { .. }
you can pass arguments to it
you can use input\output redirection
Exit a function with return
returns a status code, like exit
without a return statement, function returns status of last command
print to stdout
sum () {
echo $(( $1 + $2))
}
use status of last comman
start_with_a () {
[[ $1 == [aA]* ]];
}
To define function local variable use:
declare var_name
local var_name
To export function to subprocess use
export -f function_name
will be executed every time when function is run
fun () {} >&2
ls | some_func
- function will not get input from the ls outputGet the length of the string
${#var_name}
Removing part of a string
Example string: i=/Users/reindert/demo.txt
${var_name#pattern}
- removes the shortest match from the begining of a string
${i#*/} => User/reindert/demo.txt
${var_name##pattern}
-removes the longest match from the begining of a string
${i##*/} => demo.txt
${var_name%pattern}
- removes the shortest match from the end of a string
${i%.*} => /User/reindert/demo (remove extension)
${var_name%%pattern}
- remove the longest match from the end of a string
${i%%*.} => txt
Search and Replace.
Example string i=mytxt.txt
${var/pattern/string}
- substitute first match with a string
${i/txt/jpg} # myjpg.txt
${var//pattern/string}
- substitute all matchs with a string
${i//txt/jpg} # myjpg.jpg
${i//[jx]/a} # matat.tat
${var/#pattern/string}
- matches begining of the string${var/%pattern/string}
- matches the end of the string
${i/%txt/jpg} # mytxt.jpg
To import code in the crrent shell proces use
source myscript
source
has an allias .
To run script in backgroud use
./myscript &
To keep you script running when you exit the terminal session use
nohup myscript &
To run script with lower priority
nice myscript
To run script with lower priority in background use
nohup nice myscript &
At will execute your script at a specific time
at -f myscript noon tomorrow
Cron will execute your script according to a schedule. Also we could use upstart for this purpose