Skip to content
Linux Basics: Capture Command Output with Bash Command Substitution

Linux Basics: Capture Command Output with Bash Command Substitution

October 20, 2026

Use $(command) when a small text result belongs in a variable. Keep the result quoted, understand what happens to newlines, and check whether the producing command succeeded.

These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh. No administrator access is needed.

Prepare a scratch directory

You need Bash, a text editor, and the basename, wc, mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file in this scratch directory before running its command. Calling bash explicitly avoids changing executable permissions.

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

1. Build a short report from command results

Save this as capture-report.sh:

#!/usr/bin/env bash
filename='release notes.txt'
printf '%s\n' 'Draft' 'Review' 'Publish' > "$filename"
label=$(basename -- "$filename" .txt)
lines=$(wc -l < "$filename")
printf 'Report <%s>: %s lines\n' "$label" "$lines"

Run it:

bash capture-report.sh

Output:

Report <release notes>: 3 lines

The assignments capture the commands’ standard output. Quoted arguments preserve the space in the filename and label. The input file has three terminating newlines, so wc -l reports three. This controlled example creates its own input; check failures when reading real files.

2. See which newlines are removed

Save this as capture-newlines.sh:

#!/usr/bin/env bash
text=$(printf 'alpha\nbeta\n\n')
printf 'Value: <%s>\n' "$text"
printf 'Characters: %d\n' "${#text}"

Run it:

bash capture-newlines.sh

Output:

Value: <alpha
beta>
Characters: 10

Both trailing newlines disappear; the newline between the words remains. Quoting "$text" keeps that internal newline in one argument. Command substitution is for text, not exact binary storage: Bash variables cannot preserve NUL bytes. Use files or streams when every byte matters.

3. Check the status before using captured text

Save this as capture-status.sh:

#!/usr/bin/env bash
build_summary() {
  printf 'partial summary\n'
  return 4
}
if summary=$(build_summary); then
  printf 'Complete: %s\n' "$summary"
else
  status=$?
  printf 'Build failed: %d\n' "$status"
  printf 'Discarding: <%s>\n' "$summary"
fi

Run it:

bash capture-status.sh

Output:

Build failed: 4
Discarding: <partial summary>

A plain assignment containing this substitution receives the command’s exit status. Capture it immediately in the failure branch. Output can exist even when a command fails, as this deliberate failure shows. Standard error is not captured unless you explicitly redirect it; combining it with standard output may turn diagnostics into data. Avoid hiding the status behind a declaration such as local result=$(command); declare first, then assign.

Clean up

In the same terminal, remove only the files created for these examples, return to your original directory, and remove the empty scratch directory:

rm -- capture-report.sh capture-newlines.sh capture-status.sh 'release notes.txt'
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

References

Acknowledgements

This post was created with assistance from AI.

Last updated on