Shell Cheatsheet - Scripts
Loop
for S in FOO BAR BAZ
do
...
done
Loop in a sequence:
for i in {0..10}
With a step value using {START..END..INCREMENT}
syntax:
#!/bin/bash
for i in {0..10..2}
The other syntax to generate a sequence:
for i in $(seq 0 2 10)
Environment Variables and Shell Variables
# List all variables
$ env
$ printenv
# Show A Specific Variable
$ env | grep TERM
xterm-256color
$ echo $TERM
xterm-256color
# Remove A Variable
$ unset $VAR_NAME
env
vs printenv
: printenv
is equivelant to env
when printing env vars; env
can also be used to set env vars.
Set Environment Variable
$ x="hello" y="world" bash -c 'echo $x $y'
hello world
bash -c
: "commands are read from the first non-option argument command_string. If there are arguments after the command_string, the first argument is assigned to 0 sets the name of the shell, which is used in warning and error messages."
List of Built-in Variables
HOME
: Home directory of the user. Default is/home/<your_username>/
MAIL
- Contains the path to the location where mail addressed to the user is stored.IFS
- Internal Field Separator. Contains a string of characters which are used as word separators in the command line. The string normally consists of the space, tab and the newline characters. To see them you will have to do an octal dump:$ echo $IFS | od -bc
PS1 and PS2
- Primary and secondary prompts in bash. PS1 is set to$
by default and PS2 is set to>
. To see the secondary prompt:$ ls |
USER
- User login name.TERM
- indicates the terminal type being used. This should be set correctly for editors like Vim to work correctly.SHELL
- Determines the type of shell that the user sees on logging in. Default should be/bin/bash
on most Linux distros; macOS defaults to/bin/zsh
.LOGNAME
- login namePATH
: where to look for commands
Check and change your shell
$ echo $SHELL
$ echo $0
Change your default shell (e.g. to zsh):
$ chsh -s /usr/bin/zsh
env variable vs shell variable
- Environment variables are NOT global/system-wide. They are available in current shell and all child processes.
- Shell variables are private to the currently running shell, and they are NOT exported (passed on) to any child processes.
To make a shell variable available as an environment variable, use export VARNAME
To export or not to export?
-
If the var is expanded right here in the command / script, it can go without
export
PROJECT=foo mkdir -p tmp/$PROJECT
-
If the var is used in subprocesses, use
export
; e.g. if your build tool / script allow you to override env var likeXXX_VERSION
, you canexport XXX_VERSION
in the main script.
Alias
$ alias sayhello='echo hello'
$ sayhello
hello
To show colors by file extension
$ ls -G
To make it default, add this to ~/.bash_profile
alias ls="ls -G"
Wildcards
*
: matches any characters?
: matches one and only one character[abc]
: matchesa
orb
orc
[!abc]
: matches any characters other thana
orb
orc
{abc, def}
: matchesabc
ordef
{1..5}
: generates the sequence1 2 3 4 5
Input/Output
A shell opens 3 standard IO streams:
0
: standard inputstdin
1
: standard outputstdout
2
: standard errorstderr
They are basically file handles ("Everything is a file").
Redirect
-
<
redirectsstdin
, e.g.$ sort < /etc/group
-
>
redirectsstdout
, e.g.$ echo 'hello' > hello.txt
-
2>
redirectsstderr
, e.g.2>
will redirectstderr
toerrors.txt
:$ find / -name term 2> errors.txt
-
2>&1
assigns stream2
to1
, so allstderr
is also showing instdout
, e.g.$ find / -name term 2>&1 > all.txt $ (do whatever) > /home/ubuntu/`date +"%Y%m%d"`.log 2>&1
-
|
(a pipe) transfers thestdout
as the input of next segment
Capture the output of command line
Use backticks:
var=`command`
Use $()
:
var=$(command)
yes or no
Some commands/programs will pause to ask you y
or N
. To Answer that automatically, use yes
or yes n
for no
$ yes | xxxx
$ yes n | xxxx
Brackets
Name | Other Name | |
---|---|---|
[] |
Brackets | |
() |
Round Brackets | parentheses |
{} |
Curly brackets | braces |
<> |
Angle brackets | chevrons |
In Bash, test and [
are builtins. The double bracket enables additional functionality. For example, you can use &&
and ||
instead of -a
and -o
and there's a regular expression matching operator =~
.
The double bracket enables additional functionality. For example, you can use &&
and ||
instead of -a
and -o
and there's a regular expression matching operator =~
.
Shell Parameter Expansion
The braces, in addition to delimiting a variable name are used for parameter expansion so you can do things like:
Truncate the contents of a variable
$ var="abcde"; echo ${var%d*}
abc
Make substitutions similar to sed
$ var="abcde"; echo ${var/de/12}
abc12
Use a default value
$ default="hello"; unset var; echo ${var:-$default}
hello
and several more
Also, brace expansions create lists of strings which are typically iterated over in loops:
$ echo f{oo,ee,a}d
food feed fad
$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")
$ for num in {000..2}; do echo "$num"; done
000
001
002
$ echo {00..8..2}
00 02 04 06 08
$ echo {D..T..4}
D H L P T
Note that the leading zero and increment features weren't available before Bash 4.
Double parentheses
Double parentheses are used for arithmetic operations:
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
and they enable you to omit the dollar signs on integer and array variables and include spaces around operators for readability.
Single brackets are also used for array indices:
array[4]="hello"
element=${array[index]}
Curly brace are required for (most/all?) array references on the right hand side.
Parentheses are also used for subshells. And that they are used to create arrays.
array=(1 2 3)
echo ${array[1]}
2
[
vs [[
: http://mywiki.wooledge.org/BashFAQ/031
Quote
$'string'
: a special kind of single quotes.
- replace backslash-escaped characters (e.g.
\t
fortab
) - then function as a single quoted string.
e.g.
$ echo $'Name\tAge\nBob\t24\nMary\t36'
Name Age
Bob 24
Mary 36
:-
- Parameter substitution
:-
: e.g. ${a:-b}
, if a
is unset or null, set to b
.
# if `REGISTRY_HOST` not set, set to `HOST_IP`
export REGISTRY_HOST=${REGISTRY_HOST:-${HOST_IP}}
Shell - :?
vs ?
${parameter:?err}
: ifparameter
is null or unset, print error messageerr
${parameter?err}
: ifparameter
is unset, print error messageerr
(does NOT check null)
# a is set, not null
$ a=hello
$ echo ${a:?something went wrong}
hello
# b is not set
$ echo ${b:?something went wrong}
zsh: b: something went wrong
$ echo ${b?something went wrong}
zsh: b: something went wrong
# c is null, only :? shows error
$ echo ${c:?something went wrong}
zsh: c: something went wrong
$ echo ${c?something went wrong}
# no error
How to use param in alias?
alias
does not support params; use a function instead.
myfunction() {
echo $1
}
myfunction hello
Trap
tempfile=/tmp/tmpdata
function cleanup() {
rm -f $tempfile
}
trap cleanup EXIT
cleanup
will be called upon exit. Equivalent to a defer
statement in Swift or Go.
Shebang
The #!
is called a shebang. Scripts will execute using the interpreter specified on a first line.
Make Shell Script Portable
If you use the POSIX shell /bin/sh
, just add #!/bin/sh
to the top of your script. The location is standardized.
If you use other shells, e.g. bash, use #!/usr/bin/env bash
instead of #!/bin/bash
as shebang. Because bash is not always in the same location. If you have multiple versions of a shell installed, use env
will make sure the first executable in the PATH
will be used.
Bash Script
bash syntax: https://devmanual.gentoo.org/tools-reference/bash/index.html
Evaluate numbers
$((i-1))
Check if exists
if [ -d foo ]; then
mkdir foo
fi
Skeleton of a bash script
#!/bin/bash
usage="Usage: server.sh (start|stop)"
# command is 'start' or 'stop'
command=$1
case $command in
(start)
...
;;
(stop)
...
;;
(*)
echo $usage
exit 1
;;
esac