bash
A good cheatsheet : https://devhints.io/bash
This page was made for a job application and is not finished yet.
startup files
.profile
This is meant to do a one time setup when logging in, and .bashrc is run at every subsequent bash only startup.
bash_profile should just load .profile and .bashrc in that order.
command line options
- -x : print all commands as encountered
Also to be set in the script like so :
The -x kicks in when encountered so this would print :
Started like this would print :
| cli -x option | |
|---|---|
Try setting -x in your shell :)
variables
Important
No spaces between = and operands!
Important
All variables are strings !!!
Yes, they get converted to number when used in arithmetic.
| numeric | |
|---|---|
The result is :
| interpolation | |
|---|---|
So beware of interpolation, and single/double quotes.
comments
| comments | |
|---|---|
input
read gets one whole line upto newline :
command input
Getting the output of a command into a string can be done with back quotes
Note that wildcards are special and get expanded :
Prints this: because i have these files in my directory (1 2 3 4 and test.sh)
So enclosing the $MESSAGE in "" fixes the expansion so you can see here it happens in the echo command not the assignment !! This is done because you also want that to happen when you say :
| also | |
|---|---|
stopping
arithmetic
As said variables are always strings, when you want to do arithmetic with them you have to use let
Since everything remain strings anyway, you can just as well do :
Also x itself can participate :
Note that the quotes are needed :
| arithmetic | |
|---|---|
| arithmetic | |
|---|---|
Again the * got expanded to the files in the current directory.
You can omit the quotes if you don't use spaces, but its not very readable :
| spaces | |
|---|---|
expr and $(expr)
Another way do evaluate expression without the need for a variable because it defaults to printing the outcome. Also expr takes separate arguments, so now the spaces are actually needed.
| expr | |
|---|---|
But now you have to make effort to get it into a variable, with the ( ) and still you need to escape the wildcard !
double parentheses
This seems the best usable version :
| double (( )) | |
|---|---|
In this format you can also use /= *= \%=, ..
Important
In expression evaluation (( )) is clearly the winner.
if statements
Important
0 == true and 1 == false. YES 0 means all ok and nonzero means error in bash!!
The general format is :
| if logic | |
|---|---|
That's the one liner version and it needs terminators ; to work. Multi line and more readable and with elif variant :
| if logic | |
|---|---|
Important
when nesting be careful to close blocks with fi
To test the conditional you always use the test function, which you can just use on the commandline :
Important
Again this prints 1, because it is NOT ok(0)
However in if statements this works without showing the numbers and there is also a shortcut for the test command :
| testing | |
|---|---|
Important
Mind the spaces in the [] command, a space around all operands/operators !
If you need to compare variables, include them within DOUBLE quotes to make them single arguments to test, for instance
| compare between "" | |
|---|---|
To explain what happens, use -x again :
| -x version | |
|---|---|
Without interpolation, they are surely not the same.
comparison operators
For strings we use the standard ones, and for numbers the -gt ones.
| Operator | Purpose | For DataType |
|---|---|---|
| = | Equal to operation | string |
| == != | Equal to operation is not equal to string | string |
| < i | s less than in ASCII alphabetical | string |
| > i | s greater than in ASCII alphabetical | string |
| -z | if a string is empty (or null) | string |
| -n | if a string is not empty (or not null) | string |
| -eq | is equal to | number |
| -ne | is not equal to | number |
| -lt | is less than | number |
| -le | is less than or equal to | number |
| -gt | is greater than | number |
| -ge | is greater than or equal to | number |
Random variables
You can generate random number through a variable, the numbers are between 0 and 32767 :
sequence list
generating sequences on the fly :
| sequences | |
|---|---|
You cannot seem to assign sequences to a list or something.
for loop
syntax :
With the 'in' iterator we can walk through lists
So .. changing the '*' in the first example would just mix the sentence with the directory content.. Even this does what you think it does :
| mixing | |
|---|---|
More useful is traversing a variables content:
| traverse words | |
|---|---|
Important
If you drop the 'in x' part bash will take the commandline variables
c style loop
while do
wildcards
Sort of regular expressions, but with a different syntax. For instance . is not 'any' character but stands for directory on it's own, asterisk is the same as .* in PCRE. And more, here are some examples.
| ls | |
|---|---|
You can enable extended globbing to have more features. This command shows if extglob is enabled. It seems to be by default:
| extglob | |
|---|---|
You can now do more then before, an example :
| pattern | description | example matches |
|---|---|---|
| !(patterns) | Match anything that does not match the 'patterns' | !(photo).db photophoto.db photos.db photoss.db photosss.db |
| ?(patterns) | Match zero or one occurrences of the 'patterns' | photo?(photo).db photo.db photophoto.db |
| *(patterns) | Match zero or more occurrences of the 'patterns' | photo*(s).t* photo.txt photos.txt photoss.txt photosss.txt |
| +(patterns) | Match one or more occurrences of the 'patterns' | photo+(s).txt photos.txt photoss.txt photosss.txt |
| @(patterns) | Match one occurrence of the 'patterns' | photo@(s).db photos.db |
You can also use these patterns in [[]] expressions :
| double brackets | |
|---|---|
Note that single brackets will lead to an error here :
| single brackets | |
|---|---|
Of course the last one just tries to match "+(Error)*" literally.
switch case
| switch | |
|---|---|
Warning
case/esac does NOT fallthrough like in C. In newer bash versions you can use ;& or ;;& for that.
positional arguments
$# prints the number of arguments, not counting program. \(1-\)9 print positional parameters in functions and scripts. $* prints all arguments, excluding $0
| arguments | |
|---|---|
Calling this script with these arguments :
arrays
!/bin/bash
ARRAY=(Apple "Orange" Mango)
echo ${ARRAY[0]} # $ARRAY[0] is not valid echo "At index 1: ${ARRAY[1]}" # string interpolation ARRAY[2]=Banana # update value at index 2 ARRAY[3]=Papaya # add new value at index 3 echo ${ARRAY[2]} ${ARRAY[3]}
Note that $ARRAY[0] prints "Apple[0]" so $ARRAY evaluates to the first member. Also you can use the * wildcard to represent 'all members' so :