Skip to content

Instantly share code, notes, and snippets.

@IngmarBoddington
Last active February 14, 2022 17:23
Show Gist options
  • Save IngmarBoddington/5212780 to your computer and use it in GitHub Desktop.
Save IngmarBoddington/5212780 to your computer and use it in GitHub Desktop.
Notes on shell scripting in Linux. Should be used in conjunction with terminal notes: https://gist.github.com/IngmarBoddington/4226355
Basics
======
Expansion (special symbols replaced by values) and word splitting (arguments being split into several aruments) must have attemtion paid or pain will follow.
- # for comments
- Lots of internal variables available to bash scripts, see: http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST
- Name of script will be $0
- Parameters passed to script will be in $1, $2, $3.... vars and count in $#
- $? will return last exit message / return code for last command
- "$*" (with the quotes) returns all script arguments as single value separated by IFS
- $# number of arguments
- $@ full list of arguments as IX delimited value
- "$@" full list of args as seperate words
- $$ returns processId
- $- returns processId of last background process
- ${array[@]}: full array as IFS delimited value
- "${array[@]}": full array as seperate words
- No line terminators required but convention is semi-colon (EOL works fine)
- Use -e flag for echo's which include control characters (like \n)
- Using double quptes around variable identifiers evades word splitting arguments (single argument becoming many, often causes issues)
sh <script>
- Run script from terminal
- Don't need sh if file made executable to user
#!<commandIntepreter>
- Put at top of file to point command interpreter for rest of file (normally something like /bin/bash)
- #!/bin/sh will call the default shell interpreter
<identifier>=<value>;
- Local scalar assignment (avoid spaces around = operator)
<identifier>=(<spaceDelimitedValues>);
- List / Array assignment
- i.e. list=(item1 item2 ...) or list=([key1]=item1 [key2]=item2] ...)
$<identifier>
- Using assigned variables
exit [<string>]
- Exit with optional message
- If message is omitted the last command exit message will be returned / displayed
${<identifier>[<key>]}
- Get value of element of array
${<identifier>[@]}
- Return whole array (space delimited)
${#<identifier>[@]}
- Length of array
${#<identifier>}}
- Length of string
Capture output from command
- var=$(<command>);
- OLD: Use backticks for fetch results of bash commands, e.g. `ls` to return list of directory contents
- If failing to capture output from command, try appending 2>&1 to command (redirect stderr to stdout)
Prompting for input example (e.g.):
while true; do
read -p "Ignore (I) or Abort (A): " input
case $input in
[iI]* ) break;;
[aA]* ) exit;;
* ) echo "Please answer Ignore (I) or Abort (A): ";;
esac;
done;
IFS="<delimiter>"
- Use this to change the "Internal Field Separator" from the space default (auto list separator in loops etc)
IFS=$OIFS;
- Set IFS back to default
When entering a command the order of expansions is:
brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.
printf "format" <vars>
- Print formated string with vars interpolated (uses the standard %d, %s etc flags)
read lines from file example:
while IFS="" read -r LINE
do
echo $LINE
done < file
Control Structures
==================
If-else block:
if [ <condition> ]; then
<commands>
else
<commands>
fi;
For block
for <var> in <list>; do
<commands>;
done;
Case block
case <expression> in
<pattern1> )
<commands>;;
....
esac;
Function declaration
function <functionName> {
<commands>
}
While block
while <condition>; do
<commands
done;
Operators / Conditionals
========================
There is no concatenation operator, just put things side-by-side or use string interpolation
Comparison Operators (using 'test' / [)
Operators - format: [ <expr> <operator> <expr> ]
- Certain symbols (e.g. < redirect) should be avoided due to double meaning (use new test instead)
== is equal to (can use = instead)
!= is not equal to
-eq is equal to
-ne is not equal to
-gt is greater than
-ge is greater than or equal to
-lt is less than
-le is less than or equal to
[ $a == z* ] File globbing and word splitting take place.
[ "$a" == "z*" ] True if $a is equal to z* (literal matching).
Unary Operators - format: [ <operator> <expr> ]
-s (lowercase ‘s’) file is not zero size
-f file is a regular file (not a directory or device file)
-d file is a directory
-e file exists
-S file is a socket
-b file is a block device (floppy, cdrom, etc.)
-c file is a character device (keyboard, modem, sound card, etc.)
-p file is a pipe
-h file is a symbolic link
-L file is a symbolic link
-t file (descriptor) is associated with a terminal device
-r file has read permission (for the user running the test)
-w file has write permission (for the user running the test)
-x file has execute permission (for the user running the test)
-g set-group-id (sgid) flag set on file or directory
-u set-user-id (suid) flag set on file
-k sticky bit set
-O you are owner of file
-G group-id of file same as yours
-N file modified since it was last read
-n string is not “null.”
-z string is “null, ” that is, has zero length
f1 -nt f2 file f1 is newer than f2
f1 -ot f2 file f1 is older than f2
f1 -ef f2 files f1 and f2 are hard links to the same file
Also have 'new test' / [[ in most distros giving more options
no longer need to quote to evade word splitting of args
< is less than
<= is less than or equal to
> is greater than
>= is greater than or equal
=~ regular expression matching
[[ $<identifier = *<string>* ]] - True if string in variable
&& (and) and || (or) can be used to join [ ] / [[ ]] conditional blocks
Global Variables
================
BASH_VERSION: Contains a string describing the version of Bash.
HOSTNAME: Contains the hostname of your computer, I swear. Either short or long form, depending on how your computer is set up.
PPID: Contains the PID of the parent process of this shell.
PWD: Contains the current working directory.
RANDOM: Each time you expand this variable, a (pseudo)random number between 0 and 32767 is generated.
UID: The ID number of the current user. Not reliable for security/authentication purposes, alas.
COLUMNS: The number of characters that fit on one line in your terminal. (The width of your terminal in characters.)
LINES: The number of lines that fit in your terminal. (The height of your terminal in characters.)
HOME: The current user's home directory.
PATH: A colon-separated list of paths that will be searched to find a command, if it is not an alias, function, builtin command, or shell keyword, and no pathname is specified.
PS1: Contains a string that describes the format of your shell prompt.
TMPDIR: Contains the directory that is used to store temporary files (by the shell).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment