The VikiD Truth

Knowledge base / Computing / Linux & the command line

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:

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:

KindFound howExamples
Reserved wordparsed as syntaxif, for, [[
Builtinimplemented inside Bashcd, echo, read, test
Externallooked 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

Keywords at work: time, !, coproc and select

Four reserved words are rarely explained, and all four are worth knowing.

# time: a keyword, so it can time a whole pipeline, not just one program
time (find / -name '*.l' 2>/dev/null | wc -l)
TIMEFORMAT='%Rs real, %Us user'; time sleep 0.2

# !: negate the exit status of a pipeline
if ! grep -q vikix /etc/hostname; then echo "not on Vikix"; fi

# coproc: run a program in the background with a two-way pipe to it
coproc BC { bc -l; }
echo '4*a(1)' >&"${BC[1]}"       # send a line to bc
read -r pi <&"${BC[0]}"           # read its answer back
echo "pi is $pi"
kill "$BC_PID"

# select: an instant numbered menu
PS3='Window manager? '
select wm in stumpwm i3 quit; do
  case $wm in
    quit) break ;;
    *)    echo "You chose $wm"; break ;;
  esac
done

coproc is how you keep a long-running tool such as bc, sqlite3 or even pil open and talk to it line by line, instead of starting it again for every question. It is the shell’s version of a REPL connection.

How to check any word

When you meet an unfamiliar word in a script, ask Bash what it is before you search the web:

type -t if        # keyword
type -t cd        # builtin
type -t ls        # alias (or file)
type -t greet     # function
compgen -k        # list every keyword this Bash knows
help time         # built-in help for keywords and builtins

compgen -k is the authoritative list for the Bash you are running, which matters as new versions occasionally add words. Bash 5.3 is current in 2026 and the list has been stable for years, but compgen never goes out of date.

Connections

if	then	elif	else	fi	time

for	in	until	while	do	done

case	esac	coproc	select	function

{	}	[[	]]	!

Last edited · 2 revisions

Tags: #Computing