Site Tools


wiki:shell-io

Shell I/O and Redirection

Redirection

Redirect standard input, output, and error between files and file descriptors. File descriptor 1 is stdout, 2 is stderr, 0 is stdin.

  • > — Write stdout to file (truncates if exists)
  • >> — Append stdout to file
  • < — Read stdin from file
  • 2> — Redirect stderr to file
  • &> — Redirect both stdout and stderr
# Redirect output to file
ls > files.txt
 
# Append to file
echo "more content" >> files.txt
 
# Redirect both stdout and stderr
command > output.txt 2>&1
 
# Redirect stderr only
command 2> errors.log
 
# Discard output
command > /dev/null 2>&1
 
# Read input from file
sort < unsorted.txt

Combine redirections to separate stdout and stderr streams:

# Stdout goes to output.txt, stderr to error.txt
script.sh > output.txt 2> error.txt
 
# Send stderr to stdout
script.sh 2>&1
 
# Send stderr to stdout, then pipe to grep
script.sh 2>&1 | grep "error"

Pipelines and tee

Pipe the stdout of one command into the stdin of another with |. Chain multiple commands to transform data.

# Count lines in a file
cat myfile.txt | wc -l
 
# Chain commands: list, sort, count unique
ls | sort | uniq | wc -l
 
# Find large files and sort by size
find . -type f -exec ls -lh {} \; | sort -k5 -h

Use tee to write to a file and stdout simultaneously. Useful for logging intermediate pipeline output.

# Capture output to file while still printing it
cat data.txt | tee backup.txt | grep "important"
 
# Append mode with tee
command | tee -a logfile.txt
 
# Tee in a pipeline with multiple commands
generate_report | tee report.txt | mail -s "Report" admin@example.com

Command Substitution

Run a command and substitute its output in-place with $(command) or `command` . The $() syntax is preferred (nestable, more readable).

# Assign command output to variable
files=$(ls *.txt)
count=$(wc -l < data.txt)
 
# Use in string
echo "Found $(ls -1 | wc -l) files"
 
# Nested command substitution (only works with $(), not backticks)
total=$(( $(wc -l < file1.txt) + $(wc -l < file2.txt) ))

Be careful with whitespace: command substitution removes trailing newlines but preserves embedded whitespace. Quote variables to preserve spaces and newlines.

# Without quotes: loses structure
for file in $(ls)  # Splits on whitespace, breaks with spaces in names
    echo $file
done
 
# With quotes: preserves structure
for file in $(ls)
do
    echo "$file"  # Correctly handles spaces and newlines
done
 
# Alternative: use -print0 with while read
ls -print0 | while IFS= read -rd '' file; do
    echo "$file"
done
wiki/shell-io.md · Last modified: by 127.0.0.1