To set a variable to the output of a command in Bash, use command substitution with the $(...)
syntax. This captures the standard output (stdout) of the command and assigns it to the variable. Here’s how to do it:
Basic Syntax
variable_name=$(command_here)
or for older shells (not recommended):
variable_name=`command_here` # Backticks (legacy syntax)
Examples
1. Capture the output of date
:
current_date=$(date +"%Y-%m-%d")
echo "Today is $current_date" # Output: Today is 2023-10-05
2. Capture the list of files in a directory:
files=$(ls)
echo "Files: $files" # Lists all files in the current directory
3. Capture multi-line output (e.g., git status
):
git_status=$(git status)
echo "$git_status" # Preserves newlines and formatting
Key Notes
- Quoting:
- Always quote the variable when using it (
"$variable_name"
) to preserve whitespace, newlines, and special characters:
output=$(echo -e "Hello\nWorld")
echo "$output" # Outputs two lines: "Hello" and "World"
- Without quotes, Bash splits the output into “words” (based on spaces/tabs/newlines):
echo $output # Outputs: Hello World (collapsed into one line)
- Error Handling:
- By default, only stdout is captured. To include stderr, redirect it:
output=$(command 2>&1) # Captures both stdout and stderr
- Trailing Newlines:
- Command substitution removes trailing newlines. To preserve them, append a dummy character and strip it:
output=$(printf "Hello\n"; printf x) # Add 'x' to preserve trailing newline
output="${output%x}" # Remove the 'x'
- Exit Status:
- The exit status of the command is not stored in the variable. Use
$?
to check success/failure:
output=$(ls)
if [ $? -ne 0 ];
then
echo "Command failed"
fi
Advanced Use Cases
1. Nested Command Substitution:
combined_output=$(echo "Today is $(date +'%A')")
echo "$combined_output" # Output: Today is Thursday
2. Capture Command Output Line-by-Line:
while IFS= read -r line; do
echo "Line: $line"
done < <(command_here)
3. Store Output in an Array:
files_array=($(ls)) # Splits output into array elements (caution: spaces in filenames break this)
echo "First file: ${files_array[0]}"
Common Pitfalls
- Spaces in Filenames/Output: Use
mapfile
orreadarray
to safely store multi-word output in arrays:
mapfile -t files < <(ls) # Stores each line as an array element
echo "First file: ${files[0]}"
- Binary Data: Avoid command substitution for binary data (use pipes or redirection instead).
Summary
- Use
var=$(command)
to capture stdout. - Quote variables (
"$var"
) to preserve formatting. - Redirect stderr with
2>&1
if needed. - Prefer
$(...)
over backticks for readability and nesting.