opscape

Redirection cheat sheet

Every bash redirection operator on one page, from > and 2>&1 to here-strings, exec and process substitution.

Redirections are applied left to right before the command runs, and n>&m copies a descriptor as it is at that moment. fd 0 is standard input, 1 standard output, 2 standard error. Rows marked bash-only fail or behave differently under a POSIX sh such as dash. The full explanation is in the Redirection guide.

Output

echo one > f.txt; echo two > f.txt; cat f.txt
> writes stdout to a file, truncating it first.two
echo one >> f.txt; echo two >> f.txt; cat f.txt
>> appends to the file instead of truncating.one two
ls missing.txt 2> err.txt; cat err.txt
2> sends standard error to a file.ls: cannot access 'missing.txt': No such file or directory
ls todo.txt missing.txt > all.txt 2>&1; cat all.txt
Both streams to one file. > file must come before 2>&1.ls: cannot access 'missing.txt': No such file or directory todo.txt
ls todo.txt missing.txt 2>&1 > out.txt; echo "file has: $(cat out.txt)"
Wrong order: the error still goes to the terminal, only stdout reaches the file.ls: cannot access 'missing.txt': No such file or directory file has: todo.txt
ls todo.txt missing.txt &> all.txt; wc -l < all.txt
&> is bash shorthand for > file 2>&1; &>> appends. Bash-only.2
ls missing.txt > /dev/null 2>&1; echo "status $?"
Discard all output and keep only the exit status.status 2
echo "warning: low disk" >&2
>&2 (same as 1>&2) writes a message to standard error.

Input

wc -l < todo.txt
< connects a file to standard input; the command sees no file name.5
tr a-z A-Z <<EOF
Here-document: lines up to EOF become stdin; $var and $(...) are expanded.
cat <<'EOF'
Quoted delimiter: the here-document body is passed literally, no expansion.
cat <<-EOF
Strips leading tabs (not spaces) from body lines and the delimiter line.
tr a-z A-Z <<< "hello there"
Here-string: one expanded word plus a newline as stdin. Bash-only.HELLO THERE
read -r a b <<< "web01 10.0.0.11"; echo "$b"
Split a string into variables without a pipe or subshell.10.0.0.11

Descriptors and exec

exec 3> fd3.log; echo "via fd 3" >&3; exec 3>&-; cat fd3.log
Open fd 3 for writing, write to it, close it with 3>&-.via fd 3
exec 4< todo.txt; read -r first <&4; read -r second <&4; echo "$first / $second"
Open a file on fd 4 for reading; each read continues where the last stopped.buy milk / fix login bug
exec {log}>> app.out; echo "fd is $log"; echo hi >&$log; cat app.out
{name}> lets bash pick a free descriptor (10 or above) and stores it in $name. Bash-only.fd is 10 hi
exec > run.log 2>&1
Redirect everything the rest of the script prints.
{ echo header; sort data/fruits.txt | uniq; } > out.txt; head -n 3 out.txt
Redirect a whole group of commands, opening the file once.header apple banana
ls todo.txt nope.txt 3>&1 1>&2 2>&3 3>&- | tr a-z A-Z
Swap stdout and stderr; here only the error goes through the pipe.todo.txt LS: CANNOT ACCESS 'NOPE.TXT': NO SUCH FILE OR DIRECTORY
exec 3<> data.txt
<> opens a file for reading and writing on one descriptor.

Pipes and process substitution

ls todo.txt missing.txt 2>&1 | wc -l
Send both streams through a pipe (portable form).2
ls todo.txt missing.txt |& wc -l
|& is bash shorthand for 2>&1 |.2
ls todo.txt missing.txt 2>&1 > /dev/null | sed "s/^/ERR: /"
Pipe only standard error, discard standard output.ERR: ls: cannot access 'missing.txt': No such file or directory
diff <(sort -u data/fruits.txt) <(printf "%s\n" apple banana)
<(cmd) is a file name to read cmd's output from. Bash-only.3,6d2 < cherry < date < elderberry < fig
echo hi | tee >(tr a-z A-Z) > /dev/null | cat
>(cmd) is a file name whose contents go to cmd's stdin. Bash-only.HI

Safety

set -o noclobber; echo x > todo.txt; echo "status $?"
noclobber makes > refuse to overwrite an existing file./bin/bash: line 1: todo.txt: cannot overwrite existing file status 1
set -o noclobber; echo x >| todo.txt; cat todo.txt
>| overwrites even with noclobber set.x
sort todo.txt > todo.txt; wc -c < todo.txt
Trap: the shell truncates the output before the command reads it. Use a temp file or sort -o.0