Bash has tons of commands that print out information. While printing it to the terminal is great, there are many times when we’d like to be able to save the output for later or feed the output of one command into the input of another. Since bash is a shell, it has features that support these common tasks straight out of the box.
Input and output between programs in a Unix environment is accomplished using “streams.” A stream is just a special file that either continuously receives text in or pushes text out.
Whenever a process starts, that process is given access to three “standard” streams.
|Standard Streams||short name||number (fd)|
stdinis the type of stream that continuously receives input, and is one of the most common ways a program can receive input (other than from command line arguments).
stderrare the kind of stream that continuously send text out, and are the most common way that a process can communicate with the user or other programs.
stdoutis generally used for normal program output
stderris used to communicate something when an error has occurred.
All the streams are given a number (called a “file descriptor”), which you can see in the table.
When a process starts up normally,
stderr are configured to print
whatever they receive to the terminal screen.
stdin is configured to
continuously read input from the user’s keyboard (this is how you can
communicate with programs that prompt you for input).
Using a bit of shell syntax, we can reconfigure what
stderr are for a program. We use some combination of less than (
greater than (
>) symbols, along with a specific file where input or output
should go. There are two flavors of outputting text: we can either overwrite the
stream or append to it.
If the specified file doesn’t exist, and you’re sending output there, the file will be created.
A very common task when using redirection is to send both
to the same place. This can be accomplished by actually redirecting one to the
Sometimes, we want to ignore the output of a command. There is a special file,
/dev/null which is a null device—that is, it discards
anything written to it.
Pipes are a way to chain together the output from one command with the input to
another. Lines of shell code that uses pipes are sometimes referred to as
“pipelines.” To create a pipe, we use the Unix pipe character:
| (above the
\ character on a U.S. keyboard).
Let’s say I want to figure out the number of words in the computer’s dictionary
that contain the string “compute.” I could use the
grep program (which
searches a file for a pattern and prints all matches), and pipe the output to
wc, a program that counts the number of lines given to it.
We’ll discuss the power of pipes in more detail in the section on Bash Oneliners. Using pipes effectively is a fine art which, when mastered, can reduce some incredibly hard problems down to one line of code!
While pipes are great for sharing
stdout between processes,
sometimes we want to use the output of a command in the arguments of another.
We can accomplish this with the