STDIN, STDOUT, STDERR, Piping, and Redirecting

Advertisement

Advertisement

Introduction

Operating systems recognize a couple special file descriptor IDs:

  • STDIN - 0 - Input usally coming in from keyboard.
  • STDOUT - 1 - Output from the application that is meant to consumed by the user, stored in a file, or piped to another application for parsing. Typically goes to terminal.
  • STDERR - 2 - Used for info, debug, and error messages to the user that are not intended to specifically be part of the application output. Typically goes to terminal.

This guide will look at how you can redirect and pipe these streams for better application development and system administration.

STDOUT versus STDERR

To give an example of when to use STDOUT versus STDERR, consider an application that generates a CSV file. You want to make sure the CSV output is in the proper format so other applications can parse it properly. Well, what if there are some warnings you want to inform the user about during the CSV generation process. For example, the user is calling a deprecated method, or they didn't provide enough values for a row, so you fill them in with empty values. The warning messages should go to STDERR and the actual CSV contents should go to STDOUT. This way the user can redirect STDOUT to a file like output.csv while leaving STDERR to print out to the terminal for them to review, or piping STDERR to debug.log.

Piping

Simple piping uses | character to send the STDOUT from one application to the STDIN of the next application.

# Send STDOUT from `cat` to the STDIN of `grep`
cat file.txt | grep "some text"

# You can pipe together many commands
echo "hello world" | grep "world" | grep "wor" | grep "wo"

One nice thing about piping in Linux is that each application that is executed is run in parallel, so each application is processing its STDIN and sending its STDOUT as soon as it is received. It does not wait for the first application to completely finish before the next application runs. This makes it very efficient as all applications runs concurrently.

Another benefit is that you can avoid creating intermediary files. For example, to create a .tar.gz file, you can do it all it one step.

# Tarball up the `.py` and `.txt` files, gzip them
# and send the final gzipped contents to a `.tar.gz` file.
# The dash `-` means output to STDOUT instead of a file
tar cf - *.py *.txt | gzip > text_and_py_files.tar.gz

To pipe both STDOUT and STDERR you can use the |& operator.

echo "both stdout and stderr will get piped out" |& cat
# Equivalent to:
echo "both stdout and stderr going to same place" 2>&1 | cat

Redirect STDOUT

To redirect the standard output to a file, you can run a program like this with the > angle bracket followed by the file name. This works in Windows, Mac, and Linux.

# Redirect STDOUT to a file
python hello_world.py > output.txt

The example above will overwrite and re-create the file each time it runs. If you use two angle brackets, it will append instead of overwriting the file.

# Append to output.txt
python hello_world.py >> output.txt

Redirect STDERR

Redirecting STDERR is similar to redirect STDOUT except you must specify the file descriptor ID of 2 when redirecting.

For example:

# Redirect STDERR to `debug.log`
python hello.py 2>debug.log
# Redirect STDOUT to `stdout.log`
# Redirect STDERR to `debug.log`
python hello.py 1>stdout.log 2>debug.log

You can also redirect one stream to another. In this example, we first redirect STDOUT (1) to a file, and then we redirect to STDERR (2) to the new address of 1 (the file). Now both STDOUT and STDERR are going to all_output.log

# Redirect STDOUT to `all_output.log`
# then redirect STDERR to STDOUT (which goes to the file now)
python hello.py 1>all_output.log 2>&1

Redirect STDIN

You can also redirect the input, so instead of coming from your keyboard it comes from a file. Anything you entered in the file will be treated as if you typed it in yourself manually.

For example, if you had a Python 3 script like this:

# pyin.py
name = input("What is your name?")
email = input("What is your email?")
print("Your name is %s and email is %s" % (name, email))

Then in your input.txt file you had:

nanodano
nanodano@devdungeon.com

You could run the application like this:

python3 pyin.py < input.txt

This is essentially the same thing as running:

cat input.txt | python3 pyin.py

You can even redirect both STDIN and STDOUT at the same time.

python3 pyin.py < input.txt > output.txt

Conclusion

After reading this, you should know the difference between STDOUT and STDERR, and how to redirect them individually to output files. You should also know how to redirect STDIN to come from a file to provide input to an application.

Advertisement

Advertisement