BASH | Bash Cookbook |
Reserve Words
Here is the truth about Bash reserved words: they are not commands sitting somewhere in /bin – they are part of the language, recognised before anything is looked up. You cannot name a function if, and type if will tell you why.
What it is, in plain words
Reserved words (keywords) are tokens Bash treats specially when they appear where a command name would. The POSIX set plus Bash extensions includes:
! case coproc do done
elif else esac fi for
function if in select
then until while { }
time [[ ]]
They form the control-flow and compound-command syntax: if … then … fi, for … do … done, case … esac, { …;}, [[ … ]].
Why it matters
Seeing if as syntax, not a program, explains a whole class of errors:
If(capital I) is notif– the shell looks for a command namedIf.alias if=…does not do what you want.- Putting
ifin a variable and expanding it does not recreate anifstatement.
It also tells you what not to name your scripts and functions.
An everyday analogy: words that hold the sentence together
In English, “the”, “if”, “and” aren’t names of things – they structure the sentence. You can’t nickname a friend “If” and expect grammar to ignore it. Reserved words are the grammar of Bash.
A hands-on example
type if for [[ time
# if is a shell keyword
# for is a shell keyword
# [[ is a shell keyword
# time is a shell keyword
# These are *not* reserved – they are builtins or commands:
type cd echo test [
# cd is a shell builtin
# test is a shell builtin
# [ is a shell builtin
Keywords vs builtins vs externals:
| Kind | Found how | Examples |
|---|---|---|
| Reserved word | parsed as syntax | if, for, [[ |
| Builtin | implemented inside Bash | cd, echo, read, test |
| External | looked up on PATH | /usr/bin/ls, git |
# Compound commands – notice the keywords
if [[ -f /etc/os-release ]]; then
while read -r line; do
case "$line" in
NAME=*) echo "${line#NAME=}" ;;
esac
done < /etc/os-release
fi
# { } groups commands in the current shell; ( ) in a subshell
{ echo a; echo b; } > /tmp/out
( cd /tmp && pwd ) # parent directory unchanged
function is optional Bash sugar; name() { …; } is portable. Prefer the portable form.
! as a reserved word negates a pipeline’s exit status: if ! grep -q foo file; then …. (History expansion also uses !, which is a different mechanism – disable with set +H in scripts.)
Word boundaries and when a keyword is a keyword
Reserved words are only special in command position. After an = or as an argument they are ordinary text:
echo if for while # prints: if for while
alias_name=if # fine – not command position
# if=foo # syntax error: 'if' is reserved here
This is why type and careful quoting matter when generating scripts, and why syntax highlighters colour these words differently – they really are a different kind of token.
Common misconceptions
- "
[and[[are the same."[is a builtin (alias oftest);[[is a keyword with richer parsing and no word-splitting surprises. - "
timeis /usr/bin/time." The keywordtimetimes pipelines; the external has different flags. Usecommand timeor\timeto force the external. - “You can
exporta keyword.” No. Keywords aren’t variables. - "
{}needs no spaces."{ echo hi; }needs a space after{and a semicolon (or newline) before}. - “Reserved words are Bash-only.” Most listed above are POSIX;
[[,function,coproc,selectare Bash/ksh extensions.
Connections
- BASH, Bash if, Bash case, Bash Variables.
- Bash Cookbook.
if then elif else fi time
for in until while do done
case esac coproc select function
{ } [[ ]] !
