BASH Redirection
Standard File Descriptors
Linux systems use file descriptors to keep track of open files. Normally, three file descriptors are automatically opened for a process (running instance of a program):
File Descriptor Number | Name | Short Name | Purpose |
---|---|---|---|
0 | Standard Input | stdin | The normal input to the process. |
1 | Standard Output | stdout | The normal output from the process. |
2 | Standard Error | stderr | Error message output from the process. |
When running commands from the command line, all three of these file descriptors are connected to the terminal, so the input to process comes from the terminal (keyboard), and normal output as well as error output goes to the terminal (screen).
The meaning of these file descriptors may vary in some contexts; for example, when a program is executed as a CGI script by a webserver, the CGI standard dictates that stdin receives POSTed data from the browser, and stdout is used to send the resulting data (typically HTML) from the script. Stderr is usually sent to a logfile.
Additional file descriptors may be opened by a process.
Redirecting the Standard File Descriptors
BASH (and other shells in the Bourne family) permit input and output to be redirected, so that it does not come from or go to the terminal.
Redirecting Output
In BASH it is possible to redirect output using the >
and >>
symbols after a command and arguments, followed by the filename which will contain the redirected output. These symbols may be preceeded by a file descriptor number; if omitted, stdout is assumed. The >
symbol will truncate the file if it already exists; >>
will append to the existing file. Both symbols will create the file if it does not exist.
Some examples:
cal >calendar.txt
Runs the cal
command (which outputs a calendar of the current month by default) and places the output in the file "calendar.txt". If the file "calendar.txt" already exists, it is truncated (the existing contents are wiped out). If it does not exist, it is created.
cal 3 2025 >>calendar.txt
Appends to the calendar for March, 2008 to the file "calendar.txt". The file is created if it does not exist.
cal 16 2009 >output 2>error
This command will fail because there is no 16th month in the year 2009 (or any year!). The stdout is redirected to the file "output", but there will be no output. The stderr (error message) will be redirected to the file "error".
Redirecting Input
BASH uses the <
and <<
symbols to redirect input. The <
symbol used after a command and arguments and is followed by the filename from which input will be taken. If the input file does not exist, an error message is displayed. For example:
mail -s "Suggestion" joe@example.com <draft3.txt
This command will mail the contents of the file "draft3.txt" to joe@example.com with a subject line of "Suggestion".
The <<
symbol is only used within scripts. It is placed after a command and arguments and is followed by a text label. The lines after the command up to (but not including) the line containing the text label are used as the stdin of the command. For example:
mail -s "Warning" joe@example.com <<EOF This is a warning that the disk space on your system has fallen below 1 GB. It is recommended that you delete some files to free up additional disk space. EOF
This will use the three lines after the mail
command and before the EOF line as the stdin to the mail
command (i.e., the body of the e-mail message).
Duplicating File Descriptors
The syntax a>&b
can be used to redirect output for file descriptor a to file descriptor b. This is commonly used to redirect stdout and stderr to the same location:
cal 16 2008 >all-output 2>&1
This redirects stdout to "all-output" and then sends stderr to the same location. Note that the order of redirection matters -- if the command was written in this way the result would be different:
cal 16 2008 2>&1 >all-output
(In this case, stderr is redirected to the same place as stdout, which is the terminal, and then the stdout (alone) is redirected to the file "all-output").
A shortcut syntax permits stderr and stdout to be redirected to the same destination:
&>filename
Using Pipes
A pipe is a buffered mechanism for connecting the output of one command to the input of another. The symbol used is |
:
cal | lpr
This prints the current calendar on the (default) printer.
Multiple pipes may be used together in a long pipeline:
grep "/bin/bash$" /etc/passwd | cut -d: -f1 | sort | mail -s "Bash users" joe@example.com
This pipeline selects all BASH users from the system account file /etc/passwd, cuts out the user name, sorts them into order, and e-mails them to joe@example.com with the subject line "Bash users".
You can use the 2>&1
syntax with pipes:
ls /dev/snd/* /dev/asrf2as/423asfd 2>&1 | lpr
Both the stdout and stderr of the ls
command will be sent to the printer.
Using stdout as an Argument
The $( )
can be used to capture stdout of a command and use it as an argument to another command:
vi $(date +%Y)-notes.txt