In Linux there are three standard input streams, standard input (0 - stdin), standard output (1 - stdout), and standard error (2 - stderr). In this article we will discuss practical uses of the standard streams and their file descriptors in the bash command line and give examples of how to use each including redirection.

Standard Streams

In Linux and computer programming in general, standard streams are input and output (I/O) communication channels between a program and it's environment. The three standard streams are standard input (stdin), standard output (stdout), and standard error (stderr). Streams are usually connected to the terminal in which they are executed, but that can be changed using redirection operators and/or pipes.

Below is a graphic to help visualize the data streams and their file descriptors.

Diagram to help visualize the standard streams (stdin, stdout, stderr) and their file descriptors.

File Descriptors

Linux often represents the three standard streams as file descriptors, here is a table to help understand the relationship.

Tables showing file descriptor, name and standard stream relationship.

File descriptors are not limited to the three standard streams, but these are the most commonly used predefined streams. It is possible to create custom file descriptors, however we will not cover that in this article.

Redirection Operators

Redirection operators are a subset of control operators. They allow you to direct the input or output (stream) of your command.

The Input Operator

The input operator gives input to a command or process. The left angle bracket ( < ) represents this operator.

The Input Operator (rw)

The input operator (rw) does the same as the input operator only it opens the file in read/write mode. The left and right angle bracket ( <> ) represents this operator. If the file does not exist, it will be created. Since most input is from the keyboard or read from a file, this is rarely used.

The Output Operator

The output operator controls the command output stream. The right angle bracket ( > ) represents this operator. If the file you are redirecting to does not exist, it will be created. If it does exist, it will be overwritten.

The Output Append Operator

The output append operator does the same as the output operator only it appends data to a file. Two right angle brackets ( >> ) represent this operator. If the file you are redirecting to does not exist, it will be created. If it does exist, this command will append data to it instead of overwriting.

The Non-Standard Operators

Non-standard operators direct both standard output (stdout) and standard error (stderr). The ampersand sign followed by a right bracket or double right brackets represent these operators. One overwrites ( &> ) and one appends ( &>> ) data to the output file.

Pipe Operator

The pipe operator is used to pass the output of a command to the input of another command. The vertical bar ( | ) represents this operator. The aptly named pipe can be thought of similar to a physical plumbing pipe which moves liquid from one vessel to another. Output from a command enters the pipe on one side and leaves the pipe as input for another command on the other side.

Examples for using the pipe operator are in the sections below.

Standard Input - STDIN

Standard input is a data stream going into a program. This is often text input from a keyboard, but can also be data piped or redirected to a program.

Standard Input From Keyboard

A simple example of a program that uses standard input is the cat command. By default cat takes standard input and prints it to the display (standard output).

To test this we can use the cat command. Open a terminal and type cat, then type a line from your favorite song and hit enter.
NOTE: The cat program will do this forever, when you are finished hit CTRL+D to exit.

$ cat
Your lips move but I can't hear what you're saying
Your lips move but I can't hear what you're saying
$

Standard Input from an Input File

Standard input can also come from an input file. If you provide cat with a file as an argument, it will replace or redirect standard input from the keyboard to the data coming from that file.

To test this, enter the following command in your terminal and hit enter.

$ cat ~/.bashrc

The above command takes the argument (~/.bashrc) as standard input and outputs the content of the file on the screen.

Standard Input from Redirection

Standard input can also come from any file output using the input redirection operator which is represented by a less than sign or left pointing angle bracket ( < ). For example, you can use input redirection to achieve the same results as above like so:

$ cat < ~/.bashrc
.bashrc
Source global definitions
if [ -f /etc/bashrc ]; then
... OUTPUT TRUNCATED ...

Standard Input from a Data Pipe

So far we learned how to provide standard input from a keyboard or from a file by argument or redirection. But, you can also provide standard input from the output of another program on the input stream. This is called piping, and even if you are new to Linux you probably already encountered this concept. A pipe represented by a vertical line ( | ), basically takes output from one command and puts it into the pipe, then it comes out of the pipe on the other side and into the next command.

To test this enter the following command in your terminal.

$ head ~/.bashrc | cat

The head program outputs the first 10 lines of a file and pipes it to cat as standard input (stdin), which in turn prints it to standard out (stdout).

Standard Output - STDOUT

Standard output is a standardized stream that is sent to a display monitor by default. Often the terminal is standard output, but you can pipe or redirect output to a file, another program or device.

Standard Output to Display

You can use the output of almost any command as an example of standard output (stdout). Here we will use the stat command to get status information about a file and display it on the monitor.

$ stat ~/.bashrc
File: /home/savona/.bashrc
Size: 192 Blocks: 8 IO Block: 4096 regular file
Device: fd02h/64770d Inode: 13668265 Links: 1
... OUTPUT TRUNCATED ...

As you can see the stat command took the filename as an argument, did some processing and then displayed the statistics of that file to the monitor (stdout).

Standard Output Redirected to a File

You can redirect standard output (stdout) to a file. This is useful if you want to save the output for later use, or as a log of a script.

You can redirect stdout to a file using the output redirection operator represented by a greater than sign or right pointing angle bracket ( > ). For example, you can save the output of the stat command to a file named output.txt like so:

$ stat ~/.bashrc > output.txt

This created a file named output.txt, and places the standard output (stdout) of the stat command into it. We can verify this by reading the file.

$ cat output.txt 
File: /home/savona/.bashrc
Size: 192 Blocks: 8 IO Block: 4096 regular file
Device: fd02h/64770d Inode: 13668265 Links: 1
... OUTPUT TRUNCATED ...

Using this output redirection will overwrite any data that may exist in the file already. Use the output append operator if you want to append, represented by two angle brackets ( >> ).

$ stat ~/.bashrc >> output.txt

Standard Output Through a Data Pipe

The data pipe sends output from one command to another. Here we will pipe the output of the stat command into grep to pull only last modified time of the file.

$ stat ~/.bashrc | grep -i modify
Modify: 2019-02-03 09:03:25.750855221 -0500

The stat commands output enters the pipe and passed to grep for processing. When grep finishes processing the data, it sends the output to standard output (stdout).

Standard Error - STDERR

Standard error (stderr) is the destination for all error messages from a process. By default, this is the display screen but just like standard out, it can be redirected.

Standard Error to Display

Mistyping will certainly lead to an error displayed on the screen if you use the command line often. This is an example of standard error (stderr). Here we will feed the ls command an argument that doesn't exist, and it will tell us using stderr.

$ ls zepplin
ls: cannot access 'zepplin': No such file or directory

An error was displayed on the screen as stderr by default.

Standard Error Redirected to a File

Just like the other streams, you can redirect stderr to a file. Often used in scripting, but handy to know for anyone using the command line. To redirect stderr, you can use the same output redirection operator as you did with stdout ( > ). But this time, we have to specify that we want to redirect stderr by using the file descriptor. As shown in the table and diagram above, the file descriptor for stderr is 2. So we would redirect it like so:

$ ls zepplin 2> errors.txt

The file errors.txt now contains the errors from the output of the above command.

$ cat errors.txt 
ls: cannot access 'zepplin': No such file or directory

As we discussed in the stdout section, using the single bracket redirection will result in overwriting any data that is currently in the file. To append instead of overwrite, you have to use the append redirection ( >> ).

$ ls zepplin 2>> errors.txt

Standard Error Through a Data Pipe

You cannot directly pipe stderr to another command. This is by design to allow for complete error reporting. Here is an example of trying (and failing) to pipe stderr into grep.

$ ls zepplin floyd stones | grep zepplin
ls: cannot access 'zepplin': No such file or directory
ls: cannot access 'floyd': No such file or directory
ls: cannot access 'stones': No such file or directory

The ls command prints errors to the screen and the grep command acts as if it received no input.

However, as with most things Linux, there are multiple ways to accomplish the same task. You can redirect stderr to stdout using their file descriptors, then pipe it through grep.

$ ls zepplin floyd stones 2>&1 | grep zepplin
ls: cannot access 'zepplin': No such file or directory

We will discuss more about file descriptors in the next section.

Using File Descriptors for Redirection

Non-Standard redirection requires file descriptors. We covered all of the standard (input / output ) redirection in the above sections. Below we will outline some additional redirects using file descriptors.

File descriptors are used to redirect streams. However, you can do a lot more with file descriptors, much more than we will cover here. The intention of this section is to give you a elementary understanding of file descriptors and making you comfortable with their basic usage.

Redirect STDERR and STDOUT to Different Files.

You can redirect both stderr and stdout to a file. Here is an example:

$ ls zepplin floyd stones 1> output.txt 2> errors.txt

The above command sends stdout (File Descriptor 1) to ouput.txt and stderr (2) to errors.txt. We can verify by reading those files.

$ cat output.txt 
floyd:
dark-side-of-the-moon.txt
the-wall.txt

$ cat errors.txt
ls: cannot access 'zepplin': No such file or directory
ls: cannot access 'stones': No such file or directory

Redirect STDERR and STDOUT to Same File.

You can redirect both stderr and stdout to a single file if you wish. For this we can either redirect stderr to stdout, then stdout to a file like so:

$ ls zepplin floyd stones >alloutput.txt 2>&1

Or we can use a shorthand (non-standard) operator like so:

$ ls zepplin floyd stones &> alloutput.txt

Either command produces the same result, all stdout and stderr were sent to the alloutput.txt file.

$ cat alloutput.txt 
ls: cannot access 'zepplin': No such file or directory
ls: cannot access 'stones': No such file or directory
floyd:
dark-side-of-the-moon.txt
the-wall.txt

Using Permanent Redirection in Scripts

If you are writing a script and want to redirect data streams without appending the redirect operator or every line, you can use the exec command like this.

#!/bin/bash
# Redirect all stdout to output.txt
exec 1> output.txt
# Redirect all stderr to errors.txt
exec 2> errors.txt

You can use one, both or any number of custom file descriptors in your script.

Conclusion

Knowing the standard streams, file descriptors and redirection are an important part of being proficient on the command line. In this article we covered a lot but still only scratched the surface. I hope I touched all the basics of these topics, but if you feel I need to be corrected or should include additional information please sound off in the comments.