Bash¶
Resources¶
The Linux Documentation Project¶
BashFAQ¶
Bash Pitfalls - Collection of common mistakes
Storing command output/status in variables:
# Capture output
OUTPUT=$(command)
STATUS=$?
# Branch on status
if command
then
echo "success"
fi
if OUTPUT=$(command)
then
echo "success - ${OUTPUT}"
fi
# Pipelines
set -o pipefail
find /invalidpath | wc -l # Returns last non-zero subcommand status
{
while IFS= read -r LINE
do
printf '%s\n' "${LINE}"
done
# Handle edge case when last line isn't newline terminated
# `read` consumes LINE but returns false,
# Handle leftover partial line
if [[ -n ${LINE} ]]
then
printf '%s\n' "${LINE}"
fi
}
while IFS= read -r -d '' LINE
do
printf '%s\n' "${LINE}"
done < <(find -name "$PATTERN" -print0)
Tests¶
Bash Guide for Beginners: Test primitives
Variable is set:
if [[ -z ${VARIABLE+notset} ]]
then
# VARIABLE is not set
fi
if [[ ! -z ${VARIABLE+notset} ]]
# VARIALBE is set
fi
Variable has non-zero length:
if [[ -n ${VARIABLE} ]]
then
# VARIABLE has non-zero length
fi
if [[ -z ${VARIABLE} ]]
then
# VARIABLE either has zero length or is unset
fi
Argument count:
if [[ $# -eq 1 ]]
then
# 1 argument passed
fi
if [[ $# -gt 1 ]]
then
# More than 1 argument passed
fi
Expansion¶
Bash Guide for Beginners: Shell expansion
Order |
Expansion type |
Example |
---|---|---|
1 |
echo foo{A,B,C}bar
|
|
2 |
ls ~/.vimrc
|
|
3 |
echo ${PATH}
|
|
4 |
readlink -f $(which python)
|
|
5 |
echo $(( 365 * 24 ))
|
|
6 |
diff <(date) <(sleep 1; date)
|
|
7 |
args () {
printf "%d arguments:" "$#"
printf " <%s>" "$@"
echo
}
args hello world "how are you?"
VAR="This is a variable"
args $VAR
args "$VAR"
|
|
8 |
ls *.pyc
|
Redirection¶
From |
To |
Syntax |
---|---|---|
stdout |
|
|
stderr |
|
|
stdout |
stderr |
|
stderr |
stdout |
|
stdout & stderr |
|
|
stdout & stderr |
|
|
Builtins¶
- command
Run command ignoring any shell functions. Only shell builtin commands or commands found by searching the
PATH
are executed- help
Online help for builtin commands.
- read
Read from stdin or file descriptor. (See also: Bash Hackers Wiki)
Special Variables¶
Bash Guide for Beginners: Special parameters
- $#
Number of positional parameters.
- $*
Positional parameters, starting from position 1.
When the expansion is not within double quotes, each positional parameter expands to a separate word.
When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the
IFS
special variable.
- $@
Positional parameters, starting from position 1.
In contexts where word splitting is performed, this expands each positional parameter to a separate word; if not within double quotes, these words are subject to word splitting.
In contexts where word splitting is not performed, this expands to a single word with each positional parameter separated by a space.
When the expansion occurs within double quotes, and word splitting is performed, each parameter expands to a separate word.
- $?
Exit status of the most recently executed foreground pipeline.
- $-
Current option flags as specified upon invocation, by the set builtin command, or those set by the shell itself (such as the -i option).
- $$
Process ID of the shell. In a
()
subshell, it expands to the process ID of the invoking shell, not the subshell.- $!
Process ID of the job most recently placed into the background, whether executed as an asynchronous command or using the
bg
builtin.- $0
Name of the shell or shell script.
- $_
At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list. Subsequently, expands to the last argument to the previous simple command executed in the foreground, after expansion.
Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command.
Aliases¶
Advanced Bash-Scripting Guide: Aliases
In a script, aliases have very limited usefulness. It would be nice if aliases could assume some of the functionality of the C preprocessor, such as macro expansion, but unfortunately Bash does not expand arguments within the alias body. Moreover, a script fails to expand an alias itself within “compound constructs,” such as if/then statements, loops, and functions. An added limitation is that an alias will not expand recursively. Almost invariably, whatever we would like an alias to do could be accomplished much more effectively with a function.
StackOverflow: Watch command alias expansion
Aliases are only expanded as the first argument, or after another alias with a trailing space on the end of the command. From
bash
’shelp alias
:A trailing space in VALUE causes the next word to be checked for alias substitution when the alias is expanded.
To do this, try the following:
alias watch='watch ' alias ll='ls -l --color=tty' watch ll