Shell commands generally have input and output. By default, input comes from the standard input device (stdin), and the result is displayed on the standard output device (stdout). Typically:
- Standard input device: the keyboard
- Standard output device: the terminal, i.e., the display
When a Shell command runs, it opens three files:
- Standard input file (
stdin): file descriptor0, reads data fromstdin - Standard output file (
stdout): file descriptor1, writes data tostdout - Standard error file (
stderr): file descriptor2, writes error information to thestderrstream
But input and output can also come from other places — this is input/output redirection.
1. Output Redirection
1.1 Standard output redirection
Write a command’s standard output to a file:
command 1> log_a.txt # writes directly, overwriting the previous file
command 1>> log_b.txt # appends to the end of the previous file
Note that there’s no space between 1 and > or >> after command. If written like below, 1 becomes an argument to command instead:
command 1 > log_a.txt
Since standard output is the default, 1 can also be omitted:
command > log_a.txt
command >> log_a.txt
1.2 Standard error redirection
Standard error’s file descriptor is 2:
command 2>log_a.txt
command 2>>log_a.txt
The 2 in standard error redirection must be placed right before > or >>, with no space in between.
1.3 Redirecting both at once
command >log.txt 2>&1 # send both standard error and standard output to the same file
command 1>log_a.txt 2>log_b.txt # send them to two different files
Merging output files:
n >& m # merges output file m and n.
1.4 The special /dev/null
/dev/null is a special file: anything written to it is discarded, and if you try to read from it, you get nothing back. (It’s like a black hole.) But /dev/null is very useful — redirecting a command’s output to it has the effect of suppressing output.
command > /dev/null
command 2> /dev/null
command > /dev/null 2>&1
2. Input Redirection
This can be understood as the opposite of output redirection: input comes from a file.
2.1 Input redirection
Standard input is the keyboard, but it can also come from a file:
shell_command < filea.txt # uses the contents of filea.txt as standard input
2.2 Merging input files
n <& m # merges input file m and n.
2.3 Here documents
This means entering multiple lines of text right in the command line:
command << delimiter
document
delimiter
This passes the content between the two delimiters (document) as input to command:
- The closing
delimitermust start at column 1 — no characters before or after it, including spaces or tab indentation. - Whitespace around the opening delimiter is ignored.
Here documents can also be used inside scripts:
#!/bin/bash
cat << EOF
This is a simple lookup program for good (and bad) restaurants
in Cape Town.
EOF
3. Input and Output Redirection Together
Handling both input and output at the same time:
command < file1 >file2 # uses file1 as standard input, file2 as standard output
4. Pipe Commands
4.1 The | command
The pipe command (|) turns one command’s output into another command’s input.
A common case is filtering a directory (such as .) for files containing a specific name (such as y):
ls . | grep y
Here, the pipe command | is used to turn ls .’s output into grep’s input. Pipe commands can be chained, as in ls . | grep y | grep -v x: filtering for every file that contains y but not x.
A pipe command runs in a new thread — for example, grep y doesn’t run in the same thread as ls ..
4.2 Operating on output with xargs
A pipe command’s output doesn’t necessarily match what the next command expects as input, so sometimes it needs to be processed before being passed along — this is where the xargs command comes in. xargs (extended arguments) can do:
- Argument processing
- Reading information from a file as input
xargs needs a command after it to process further input; if not specified, it defaults to echo. Although xargs’s input can contain spaces and newlines, after being processed by echo, they all become spaces.
ls . | ls -l
This errors out because ls -l’s input isn’t valid — it needs to be converted with the xargs command:
ls . | xargs ls -l
Common options are as follows; to illustrate, some example files are set up here.
➜ cat x.txt
shell_00.md
shell_01.md
shell_02.md
shell_03.md
shell_04.md
shell_05.md
-
-a xx: gets input from a file➜ xargs -a x.txt file shell_00.md: Unicode text, UTF-8 text shell_01.md: Unicode text, UTF-8 text shell_02.md: Unicode text, UTF-8 text shell_03.md: Unicode text, UTF-8 text shell_04.md: Unicode text, UTF-8 text shell_05.md: Unicode text, UTF-8 text -
-p: asks the user once before running each set of arguments — entery+ Enter oryes+ Enter to confirm, or just Enter alone to skip:➜ xargs -a x.txt -p file file shell_00.md shell_01.md shell_02.md shell_03.md shell_04.md shell_05.md?...yes shell_00.md: Unicode text, UTF-8 text shell_01.md: Unicode text, UTF-8 text shell_02.md: Unicode text, UTF-8 text shell_03.md: Unicode text, UTF-8 text shell_04.md: Unicode text, UTF-8 text shell_05.md: Unicode text, UTF-8 text -
-n num: the number of arguments used per invocation of the command; by default all of them are used, and if there are more arguments than this number, it runs in multiple batches.➜ xargs -a x.txt -p -n 2 file file shell_00.md shell_01.md?...yes shell_00.md: Unicode text, UTF-8 text shell_01.md: Unicode text, UTF-8 text file shell_02.md shell_03.md?...yes shell_02.md: Unicode text, UTF-8 text shell_03.md: Unicode text, UTF-8 text file shell_04.md shell_05.md?...yes shell_04.md: Unicode text, UTF-8 text shell_05.md: Unicode text, UTF-8 text -
-t: prints the actual command being run before running it -
-ior-I: assigns each item fromxargs, generally line by line, to{}, which can be used in the command -
-r(no-run-if-empty): stopsxargsfrom running at all if its input is empty -
-Lor-l num: readsnumlines at a time from standard input to pass to the following command➜ xargs -a x.txt -t -L 2 file file shell_00.md shell_01.md shell_00.md: Unicode text, UTF-8 text shell_01.md: Unicode text, UTF-8 text file shell_02.md shell_03.md shell_02.md: Unicode text, UTF-8 text shell_03.md: Unicode text, UTF-8 text file shell_04.md shell_05.md shell_04.md: Unicode text, UTF-8 text shell_05.md: Unicode text, UTF-8 textThis needs to be distinguished from
-nabove: this one refers to the number of input lines, while-nrefers to the number of output arguments. -
-d delimiter: the delimiter, by default a space, used to splitxargs’s input➜ echo "ambmcmdm" | xargs -dm a b c d -
-eor-E flag:estands for “end” —flagmust be a whitespace-separated marker, andxargsstops as soon as it encounters this marker -
-s num: the maximum number of characters in the command line, i.e., the maximum length of the command line followingxargs -
-x(exit): used together with-s -
-P: changes the maximum number of processes; the default is 1, and 0 means as many as possible.
4.3 The tee command
tee reads data from standard input and also writes its content out to a file. Common options:
-aor--append: appends to the end of an existing file instead of overwriting it.-ior--ignore-interrupts: ignores interrupt signals.
5. Summary
This article covered input/output redirection in Shell, along with using pipe commands to feed one command’s output as another command’s input, and introduced the xargs and tee commands.