Bash / Basic: syntax, values, and control / Lesson 1
Read Bash as a command language
Follow lexical words, shell grammar, expansion, redirection, command lookup, and status instead of treating a line as an opaque string.
On this page
Lesson goals
- Distinguish parsing from expansion and command execution.
- Explain builtin and external command boundaries.
- Choose Bash explicitly when its language features are required.
The shell interprets structure before data
Bash is both an interactive shell and a programming language that connects commands. It first recognizes lexical words and operators, parses grammatical structures, performs applicable expansions, sets up redirections, and executes the resulting command. Spaces in source can separate words, while quotes preserve selected meanings. A semicolon written as shell syntax separates commands; a semicolon obtained from a quoted variable is ordinary data. This distinction is fundamental: building a string that resembles a command is not the same as constructing the command’s argument list.
Names resolve within an execution context
A command name can identify a function, builtin, or executable selected through PATH, with other interactive mechanisms such as aliases also influencing input. Builtins can affect the current shell directly; an external child cannot rewrite its parent’s working directory. Inspect resolution when a command behaves differently from expectations. Scripts should not depend on personal aliases or interactive startup files. Keep the interpreter and required tools in the script’s contract rather than assuming every machine’s sh name refers to Bash or that a familiar command always has one implementation.
printf 'builtin=%s\n' "$(type -t printf)"
printf '%s\n' 'two words'
builtin=builtin
two words
type is queried inside Bash; the second printf receives one quoted string. Both operations are self-contained and read no host files.
Expansion changes values and sometimes word count
Bash applies brace expansion before parameter expansion and later performs word splitting and filename expansion where applicable. Quote removal removes quote syntax from the original source, not quote characters that happened to appear in a variable’s data. Consequently, storing quotation marks inside a variable does not recreate source-level grouping. Quoted "$@" and quoted array expansions preserve an existing list; an ordinary quoted scalar preserves one value. Learn these boundaries before adding more escapes to a broken command. The next lesson examines splitting and globbing in detail using controlled synthetic inputs.
Grammar defines when commands run
A list can sequence commands or use conditional operators. command_a && command_b executes the second only after a zero status from the first; || handles a nonzero status. Parentheses create a subshell grouping, while braces group commands in the current shell when no other context creates a child environment. These constructs have grammar rules, including separators around brace groups. They are not interchangeable punctuation. Use small examples to predict control flow before writing a long automation line, and prefer readable multi-line structure when several conditions or side effects must be reviewed.
value=outer
(value=inner; printf 'child=%s\n' "$value")
{ value=group; }
printf 'parent=%s\n' "$value"
child=inner
parent=group
The child assignment is isolated, while the brace group changes the current shell’s value. The example changes only its own local process state.
Separate Bash requirements from POSIX sh
A shebang selects an interpreter when a script is executed directly; invoking bash file explicitly selects Bash. Invoking sh file instead asks that sh implementation to interpret it, so Bash arrays and other extensions may fail even if the first line names Bash. POSIX mode changes some Bash behavior but is not a complete substitute for testing a portable script under its target shells. Record the installed version and consult matching documentation for newer features. This course validates examples with a declared Bash version and labels extension-dependent behavior rather than calling every shell feature universal.
Common errors and fixes
Quotes stored in data are expected to group arguments
- Why it happens
- Data was confused with already-parsed shell syntax.
- How to fix it
- Construct quoted arguments or an array directly.
- Prevent it next time
- Separate source grammar from expanded values.
A child cd is expected to move the parent
- Why it happens
- The execution boundary was ignored.
- How to fix it
- Change directory in the intended shell or group.
- Prevent it next time
- Mark current-shell and child operations in the design.
Running Bash syntax through sh
- Why it happens
- The selected interpreter does not provide the extension.
- How to fix it
- Invoke the required interpreter or rewrite portably.
- Prevent it next time
- Declare the language requirement before implementation.
Check your understanding
1. Why is a semicolon in "$value" not a second command?
Show worked solution
The shell parsed operators before expanding the variable. Quoted expansion supplies data to an argument; it does not restart parsing. A separate evaluation mechanism would introduce another parse and a security boundary that ordinary argument passing avoids.
2. Choose a launch command for a script that requires associative arrays.
Show worked solution
Select a Bash version supporting that feature and run bash script.sh, or use a correct Bash shebang for direct execution. Do not use sh script.sh as a substitute. Include the requirement in usage or installation documentation.
Key takeaways
- Reason about grammar, expansion, arguments, and environment separately.
- Make interpreter requirements explicit.