IO Redirection

By default, every process has three associated file descriptors:

  • standard input (0),
  • standard output (1) and
  • standard error (2).

For these,

  • Your keyboard is the default source of standard input.
  • Your monitor is the default target for standard output, and
  • Your monitor is also the default target of standard error (which is why you even see those error messages).

The critical thing to know is that a command’s input and/or output can be redirected to another command or to a file.

Redirection

Consider the ways you can do this:

Send Standard Output To a File

> file_name # or 1> file_name
Connect standard output to the file file_name. This allows you to save the output of a command to a file. If the file doesn’t exist, it is created. If it does exist, it is destroyed or “clobbered” and then re-created:

who > users.log

who 1> users.log

If no number precedes > or >>, the shell assumes you’re redirecting Standard Output, i.e. 1.

How do you check the success of output redirection?

who > users.log || echo "who did not redirect to users.log!"

Get Standard Input From a File

< file_name

Connect standard input to the file file_name. This allows you to have a command read from the file, rather than entering input by hand. Note that there is a difference in the output of:

wc -l users.log
2 users.log

versus:

wc -l < users.log
2

Sending nothing to a file, like this:

>myfile

This will clear the contents of the file. This is a shell “shortcut” that is sometimes used to clear log files.

How do you check the success of input redirection?

wc -l < users.log || echo "who did not redirect to wc -l!"

Append Standard Output to a File

> file_name

Connects standard output to the file file_name. Unlike >, however, the output of the command is appended to the file. If the file doesn’t exist it is created.

who >> users.log
who 1>> users.log
wc -l < users.log

How do you check the success of append redirection?

who >> users.log; tail users.log

Comment out the second half of this line after debugging.

Accept Standard Input Until a Keyword Appears

file.txt<<key_word
Hamlet.txt<<Denmark

This construct causes standard input to come from a file, but only until key_word appears on a line by itself. There must be no space between << and key_word.

By default, << acts like double quotes (i.e., variables are expanded). If, however, key_word is quoted, then << acts like single quotes.

How do you check the success of keyword redirection?

Hamlet.txt<<Denmark; cat Hamlet.txt

Comment out the second half of this line later.

Redirect Standard Error (2) to a File

You can capture error messages that would otherwise be printed to the screen. This is good for logging the success of many kinds of user interactions. To see this compare the output of:

cat foo > users.log

versus:

cat foo > users.log 2>> errors.log

(run cat errors.log to see the result).

What did we just do here? Note that I/O redirections are parsed in the order they are encountered, from left to right. This allows you to do fairly tricky things, including throwing out standard output, and piping standard output to a command.

How do you check the success of StdErr redirection?

cat foo > users.log 2>> errors.log

cat users.log; cat errors.log

Comment out this line later.

Send 0, 1 or 2 to 0, 1 or 2

 2>&1 

Sends standard error (2) to standard output (1)

Think of this as meaning something like, “Send standard error to the same place as standard output.”

This formulation maps any file descriptor to any other: digitA is sent to digitB. Now is a good time to recall that standard error is usually sent to the terminal screen, even if standard output is being written to a file or piped to another command. You can capture error messages that otherwise would flash on the screen and then be lost with code like:

echo "Error: Parameter(s) Missing." 1>>log.file 2>&1

In this case the echoed message isn’t written to the terminal screen; it’s written to log.file. Notice that this is a two-step process.

First, standard output from the echo command is sent (via 1>>, though >> could have been used) to log.file.

Then standard error is also sent to standard output, which writes it to log.file as well. The example above shows how to map standard output and standard error to the same file.

You must use this notation when you send both Standard Output and Standard Error to the same file:

echo "Error: Parameter(s) Missing." 1>>log.file 2>&1 

If you try this notation:

cat foo 1>test.log 2>test.log

you will experience data loss!

Here’s one way to send 1 and 2 to different files:

cat foo 1>>test.log 2>>error.log

Run cat test.log and you’ll see it’s empty (assuming you don’t really have a file named foo), while error.log contains the error message.

This construct is also useful for printing error messages:

echo "Danger! Danger Will Robinson!" 1>&2

If you run this line in the middle of a procedure, even if output is otherwise being written to a file, the echoed error (or “danger”) message will print to the screen anyway.

Send 0, 1 or 2 to Standard Input

<&digit

Use file descriptor digit as standard input. For example, <&1 sends standard output (1) to standard input (0). This is the same as simply using < if you are only using <&1 , but <&2 is of course very different.

Close Standard Input or Output

<&- 

Close standard input.

>&- 

Close standard output.