SH

Redirects & Pipes

Bash & Linux · 9 entries

Redirect Standard Output

syntax
command > file
command >> file
example
echo 'server.port=8080' > app.properties
date >> deployment.log
psql -c 'SELECT * FROM users' > users_export.csv

Note > overwrites the file completely. >> appends to the end. WARNING: Redirecting to a file you are also reading from (e.g., sort file > file) will truncate it to zero bytes. Use a temporary file or sort -o file file instead.

Redirect Standard Error

syntax
command 2> file
command 2>> file
command 2>/dev/null
example
find / -name 'pg_hba.conf' 2>/dev/null
gcc main.c 2> compile_errors.log

Note File descriptor 1 is stdout, 2 is stderr. 2>/dev/null discards error messages (useful for suppressing 'Permission denied' noise from find). 2>> appends errors to a file.

Combine Stdout & Stderr

syntax
command > file 2>&1
command &> file
command 2>&1 | other
example
make build > build.log 2>&1
./run_tests.sh &> test_results.log
curl https://api.example.com 2>&1 | tee response.log

Note 2>&1 means 'send stderr to wherever stdout is going'. Order matters: > file 2>&1 works (redirect stdout to file, then stderr to stdout's destination). 2>&1 > file does NOT capture stderr to the file. &> is a Bash shorthand for both.

Pipes

syntax
command1 | command2 | command3
example
cat access.log | grep 'POST' | awk '{print $7}' | sort | uniq -c | sort -rn | head -10
output
    847 /api/users
    623 /api/orders
    412 /api/auth/login

Note Each | sends the stdout of the left command to the stdin of the right command. If any command in the middle fails, data just stops flowing. Use set -o pipefail in scripts to catch errors in any part of the pipe, not just the last command.

/dev/null: The Data Black Hole

syntax
command > /dev/null
command > /dev/null 2>&1
example
if command -v docker > /dev/null 2>&1; then
  echo 'Docker is installed'
fi
crontab_job: */5 * * * * /opt/scripts/cleanup.sh > /dev/null 2>&1

Note /dev/null discards anything written to it. Redirecting both stdout and stderr to /dev/null completely silences a command. Common in cron jobs and conditional checks where you care about the exit code, not the output.

Here Document

syntax
command <<DELIMITER
text
DELIMITER
example
cat <<EOF > /etc/nginx/conf.d/app.conf
server {
    listen 80;
    server_name app.example.com;
    location / {
        proxy_pass http://localhost:3000;
    }
}
EOF

# Suppress variable expansion:
cat <<'EOF'
Use $HOME to reference your home directory
EOF

Note Variables and commands are expanded inside a here document by default. Quoting the delimiter ('EOF') disables expansion, which is useful when writing scripts or config files that contain $ characters. <<- strips leading tabs (not spaces) for cleaner indentation.

Here String

syntax
command <<< "string"
example
grep 'error' <<< "$LOG_OUTPUT"
bc <<< '2.5 * 3.7'
read -r first last <<< "Ada Lovelace"
output
9.25

Note Here strings feed a string directly to a command's stdin without needing echo and a pipe. More concise than echo "string" | command. A Bash feature not available in POSIX sh.

Process Substitution

syntax
<(command)
>(command)
example
diff <(ssh web01 'cat /etc/nginx/nginx.conf') <(ssh web02 'cat /etc/nginx/nginx.conf')
paste <(cut -d',' -f1 data.csv) <(cut -d',' -f3 data.csv)

Note <(command) creates a virtual file containing the command's output. This allows commands that require filename arguments to read from a pipeline. Works only in Bash and Zsh, not POSIX sh.

Tee: Save & Pass Through

syntax
command | tee file | next_command
example
deploy.sh 2>&1 | tee deploy_$(date +%Y%m%d).log | grep -E 'ERROR|WARNING'

Note tee writes its input to a file and also passes it through to stdout. This lets you save intermediate pipeline data while still processing it downstream. Use -a to append rather than overwrite the file.