Source: Bash Scripting — Connected Objects

Variables

a=375                          # assign (NO spaces around =)
hello=$a                       # assign from variable
echo $hello                    # reference: 375
echo ${hello}                  # preferred form with braces: 375
 
right_now="$(date +"%x %r")"  # command substitution

Rules:

  • Variable names: start with letter, no whitespace or punctuation
  • Reference: $varname or ${varname} (braces = more robust)
  • No spaces around = when assigning

Environment variables

export MYVAR=Value             # export to child processes
printenv                       # list all env vars
echo $SHELL                    # read a specific env var

Quoting

Quote typeWhat it does
"double"Interprets $var and \ — protects special chars except those
'single'Treats EVERYTHING literally — no variable substitution
\charEscape single character
var="hello world"
echo "$var"    # → hello world (preserved as one argument)
echo '$var'    # → $var (literal, no substitution)
echo $var      # → hello world (but word-splitting can cause issues)

Always quote variable references: "$var" not $var (prevents word splitting).

Functions

# Definition must come BEFORE use
system_info()
{
    echo "function called"    # must have at least one valid command
}
 
# Call (no brackets)
system_info

Positional parameters

greet()
{
    local name="$1"           # local = function-scoped variable
    local age="$2"
    echo "Hello $name, age $age"
}
greet "Alice" 30
VariableMeaning
$0Script/function name
$1$9Positional arguments 1–9
$#Number of arguments
$?Exit status of last command

Conditionals

Exit status

  • 0 = success, non-zero = failure
  • $? = exit status of last command
ls /usr/bin
echo $?    # → 0 (success)
 
ls /nonexistent
echo $?    # → 2 (failure)

if / test / [ ]

if [ expression ]; then
    commands
elif [ expression ]; then
    commands
else
    commands
fi

test expressions

ExpressionTrue if
-d filefile is a directory
-e filefile exists
-f filefile exists and is a regular file
-r filefile is readable
-w filefile is writable
-x filefile is executable
-z stringstring is empty
-n stringstring is not empty
string1 = string2strings are equal
string1 != string2strings are not equal
file1 -nt file2file1 is newer than file2
file1 -ot file2file1 is older than file2
if [ -f .bash_profile ]; then
    echo "File exists"
fi
 
if [ $# -gt 0 ]; then
    echo "Got $# arguments"
fi

exit

exit 0    # success
exit 1    # failure (convention)

Shebangs

#!/bin/bash              # hardcoded path (common)
#!/usr/bin/env bash      # portable — recommended
#!/usr/bin/env python    # for python scripts

Always use #!/usr/bin/env <interpreter> for portability.

Permissions (chmod)

Viewing permissions

ls -l file.txt
# -rwxr--rw- 1 user user 0 Jan 19 file.txt
#  ^^^: owner (rwx=7)
#     ^^^: group (r--=4)
#        ^^^: world (rw-=6)

Numeric chmod

ValuePermission
4read (r)
2write (w)
1execute (x)
chmod 777 file     # rwxrwxrwx — everyone full access
chmod 755 file     # rwxr-xr-x — owner full, others read+exec (scripts)
chmod 644 file     # rw-r--r-- — owner read+write, others read only (files)
chmod 700 file     # rwx------ — owner only
chmod 400 file     # r-------- — read-only by owner

Symbolic chmod

chmod u+x script.sh       # add execute for user/owner
chmod a+r file.txt        # add read for all
chmod a-x file.txt        # remove execute for all
chmod go+rw file.txt      # add read+write for group and others
chmod -R 755 /path/dir/   # recursive

chown

sudo chown kate file.txt          # change owner
sudo chown :mygroup file.txt      # change group
sudo chown kate:mygroup file.txt  # change both

source vs bash

CommandEffect
source file.sh (or . file.sh)Runs in CURRENT shell — variables/functions persist
bash file.shRuns in NEW shell — variables/functions don’t persist to parent

Use source for libraries; use bash (or ./script.sh) for scripts.

See Also