Unix Shell Reference: Arguments, Files and Exit Status - Yenra

Keep command arguments intact, control file redirection and diagnose shell-script results.

Open reference book beside channels carrying small data blocks into an output tray.
Conceptual illustration: arguments, streams and status connect small shell commands.

Use the shell to connect small programs through arguments, files and exit statuses. This reference focuses on the points where scripts commonly change meaning: quoting, redirection, pipelines and tests. The examples use POSIX-style shell syntax unless a Bash feature is explicitly identified.

The shell running your terminal and the interpreter running a script can differ. sh script.sh selects sh; bash script.sh selects Bash. A shebang selects an interpreter when the operating system executes a file directly. Check the environment where the script will actually run, including its working directory and PATH.

Keep arguments intact

A command receives a list of arguments. Quoting helps preserve that list as data moves through variables. Try this self-contained example in sh or Bash:

show_args() {
  printf 'count=%s\n' "$#"
  for arg in "$@"; do
    printf '<%s>\n' "$arg"
  done
}
show_args 'two words' '*.txt' ''

Expected output:

count=3
<two words>
<*.txt>
<>

"$@" preserves each incoming argument, including an empty one. "$*" joins arguments into one word using the first character of IFS. Unquoted expansions can undergo field splitting and filename expansion. Those distinctions explain why a script may work with report.txt yet fail with annual report.txt. The POSIX rules for special parameters and expansion define the behavior.

Patterns to keep close at hand

Patterns to keep close at hand
Task Pattern Interpretation
Print a value printf '%s\n' "$value" Fixed format, data supplied separately
Test a readable file [ -r "$file" ] Spaces around [ and ] are required
Supply file input command < "$file" The shell opens the file for standard input
Replace output command > "$out" Opens and truncates the destination before execution
Append output command >> "$out" Opens the destination for append
Send a diagnostic printf '%s\n' 'failed' >&2 Writes to standard error
Run after success first && second Runs second if first returns zero
Run after failure first || recover Runs recover if first returns nonzero

Always consider when a destination is opened. Redirecting a failing command directly onto your only good report can leave an empty or partial report. For a replace-on-success workflow, generate a temporary file in the destination directory and promote it only after checking success. The SQLite report exercise provides a complete example with cleanup and explicit assumptions.

Separate output from status

Standard output carries results, standard error carries diagnostics, and the exit status tells the caller how execution ended. Zero conventionally indicates success. The meaning of other values belongs to the command: consult its manual before treating every nonzero value as the same event.

if output=$(printf '%s\n' 'ready'); then
  printf 'result=%s\n' "$output"
else
  printf '%s\n' 'Command failed' >&2
fi

This prints result=ready. Command substitution removes trailing newline characters, so it is unsuitable for preserving arbitrary file bytes. Keep binary data in files or streams.

A pipeline connects one command's output to the next command's input. In common default configurations, its status comes from the final command. A producer can fail while its consumer succeeds. Bash offers set -o pipefail; support and defaults vary across deployed shell versions. For a script that must run in older environments, test each important stage explicitly or document the interpreter and options it requires. The Bash pipeline documentation specifies Bash's behavior.

Read text without losing spaces

For a small line-oriented text file named names.txt, this loop preserves leading and trailing spaces and treats backslashes literally:

while IFS= read -r line || [ -n "$line" ]; do
  printf '<%s>\n' "$line"
done < names.txt

The final condition processes an unterminated last line. This is a text-record pattern; it does not preserve newline terminators or support embedded NUL bytes. When parsing CSV, use a CSV parser or database importer because quoted fields can contain commas and line breaks.

Diagnose with a small fixture

First record the exact command, interpreter version, working directory and observed status. Reduce the input to two or three fabricated records. Test a space, an empty value and a failure. Run the interpreter's syntax check, then inspect execution with tracing only when the values are safe to display.

Keep expected output beside the fixture so future changes have a baseline. For a complete first script, use the Bash line-counting guide. For an inherited KornShell job, begin with the KornShell maintenance checklist to establish its actual runtime before changing syntax.