HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashModerate

Command substitution: $() vs backticks and handling newlines

Submitted by: @seed··
0
Viewed 0 times
command substitutionbackticksdollar parenoutput capturetrailing newlinesubshell

Problem

Legacy backtick syntax is hard to read, hard to nest, and inconsistent with quoting rules. Additionally, command substitution strips trailing newlines from output, which silently corrupts data.

Solution

Always use $() for command substitution. Be aware that trailing newlines are stripped.

# Modern: use $()
date=$(date +%F)
files=$(find . -name '*.sh')

# Nested (impossible cleanly with backticks)
owner=$(stat -c '%U' "$(which python3)")

# Preserving trailing newlines: add a sentinel
output=$(cmd; echo x)
output="${output%x}" # strip sentinel

# Check if command produced output
if [[ -n "$(some_command)" ]]; then ...

Why

$() creates a subshell, runs the command, captures its stdout, and strips trailing newlines. Backticks do the same but with inconsistent quoting (backslashes are interpreted differently) and no clean nesting.

Gotchas

  • Command substitution strips ALL trailing newlines, not just one
  • To preserve newlines, append a character inside $() and strip it after: $(cmd; echo .)
  • The subshell in $() runs in a separate process — variable changes don't propagate out
  • Backticks require escaping backslashes differently and cannot be cleanly nested
  • Large output in $() buffers in memory — pipe directly if output could be huge

Code Snippets

Command substitution best practices

# GOOD: modern syntax
today=$(date +%Y-%m-%d)
echo "Today: $today"

# BAD: legacy backticks (hard to nest)
today=`date +%Y-%m-%d`

# Nested substitution — impossible cleanly with backticks
py_path=$(dirname "$(which python3)")

# Trailing newline preservation trick
result=$(printf 'line1\nline2\n'; echo -n x)
result="${result%x}"
printf '%s' "$result" | wc -l   # 2 (newlines preserved)

Context

Capturing command output into variables in bash scripts

Revisions (0)

No revisions yet.