opscape

Special variables cheat sheet

The shell's special parameters ($?, $@, $$, $!, ...) and bash's built-in variables (PIPESTATUS, BASH_SOURCE, LINENO, RANDOM, ...) with real output.

Special parameters ($?, $#, $@ ...) are set by the shell and cannot be assigned to. Bash adds many ordinary-looking variables that it maintains itself. Rows that start with bash -c '...' name a b set $0 to name and the positional parameters to a b, the same way running a script with arguments does.

Script and arguments

bash -c 'echo "0=$0 1=$1 2=$2 count=$#"' myscript alpha beta
$0 is the script name, $1..$9 the arguments, $# how many there are.0=myscript 1=alpha 2=beta count=2
set -- a b c d e f g h i j k; echo "${10} ${11} but \$10 is $10"
From the tenth argument on, braces are required: $10 is $1 followed by 0.j k but $10 is a0
set -- "one two" three; for a in "$@"; do echo "[$a]"; done
"$@" expands to every argument as a separate word, spaces preserved. Almost always the one you want.[one two] [three]
set -- "one two" three; IFS=,; echo "$*"
"$*" joins all arguments into one word, separated by the first character of IFS.one two,three
set -- a b c; shift; echo "$# left: $*"
shift drops $1 and renumbers the rest.2 left: b c
f() { echo "${FUNCNAME[0]} got $# args, first=$1"; }; f x y
Inside a function the positional parameters are the function's own arguments.f got 2 args, first=x

Status and processes

grep -q nothing todo.txt; echo "status $?"
$? is the exit status of the most recent command (0 means success).status 1
false | true | (exit 3); echo "${PIPESTATUS[@]}"
PIPESTATUS holds the status of every command of the last pipeline. Bash-only.1 0 3
echo "shell $$, parent $PPID"; ( echo "subshell: \$\$=$$ BASHPID=$BASHPID" )
$$ is the PID of the main shell, even in a subshell; BASHPID is the current process.shell 6351, parent 1 subshell: $$=6351 BASHPID=6352
sleep 1 & echo "started $!"; wait $!; echo "it exited with $?"
$! is the PID of the most recent background job.started 6354 it exited with 0
echo "$-"; set -eu; echo "$-"
$- lists the current single-letter shell options (e, u, x, ...).hBc ehuBc

Where am I

echo 'echo "${BASH_SOURCE[0]} line $LINENO"' > where.sh; bash where.sh
LINENO is the current line; BASH_SOURCE[0] is the file being executed (empty under bash -c).where.sh line 1
outer() { inner; }; inner() { echo "${FUNCNAME[*]}"; }; outer
FUNCNAME is the call stack of function names, innermost first.inner outer
cd data; cd ../logs; echo "now $PWD, before $OLDPWD"
PWD and OLDPWD are kept by cd; cd - goes to OLDPWD.now /home/dev/demo/logs, before /home/dev/demo/data
echo "$BASH_VERSION / ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
The running bash version as a string and as an array of numbers.5.2.37(1)-release / 5.2
echo "$HOSTNAME $OSTYPE $MACHTYPE"
Host name and the platform bash was built for.demo linux-gnu x86_64-pc-linux-gnu
echo "user $USER uid $UID euid $EUID home $HOME"
UID/EUID are set by bash (read-only); USER and HOME come from the login environment.user dev uid 1000 euid 1000 home /home/dev

Time and randomness

SECONDS=0; sleep 1; echo "took ${SECONDS}s"
SECONDS counts seconds since the shell started, or since you assigned it.took 1s
echo "$EPOCHSECONDS $EPOCHREALTIME"
Unix time in seconds and with microseconds, without running date (bash 5.0+).1793478174 1793478174.297820
echo "$RANDOM $RANDOM $(( RANDOM % 6 + 1 ))"
RANDOM gives 0..32767 per read. Not for secrets; SRANDOM (5.1+) gives 32-bit values from the system's random source.20490 23487 5

Parsing and input

printf '%q\n' "$IFS"
IFS is the field separator for word splitting and read: space, tab, newline by default.$' \t\n'
read <<< " keep spaces "; echo "[$REPLY]"
read with no variable name stores the whole line, unstripped, in REPLY.[ keep spaces ]
[[ "v2.4.1" =~ ^v([0-9]+)\.([0-9]+) ]]; echo "${BASH_REMATCH[@]}"
BASH_REMATCH holds the whole =~ match and each capture group.v2.4 2 4
set -- -v -o out.txt file; while getopts vo: opt; do echo "$opt ${OPTARG-}"; done; echo "OPTIND=$OPTIND"
getopts puts an option's value in OPTARG and the next argument index in OPTIND.v o out.txt OPTIND=4
echo one two three > /dev/null; echo "$_"
$_ is the last argument of the previous command.three

Prompts and tracing

PS4='+ line $LINENO: '
PS4 prefixes each set -x trace line; adding $LINENO shows where each command is.
BASH_XTRACEFD=5
Send set -x output to file descriptor 5 instead of standard error.
PS1='\u@\h:\w\$ '
The interactive prompt; \u user, \h host, \w working directory.
TMOUT=300
An interactive shell exits after this many idle seconds; read uses it as a default timeout.