Home > OS >  What is the meaning of this shell command?
What is the meaning of this shell command?

Time:10-10

I'm currently learning Shell notation, and I ran across the following command:

./a.out < infile 2>&1 > outfile

where infile and outfile are names of files.

I think what this command does is to

  1. set "standard input" to "infile"
  2. redirect "standard error" to "standard output"
  3. set "standard output" to "outfile"

Is my interpretation correct? If not, how should I understand this command?

CodePudding user response:

TL;DR: 2>&1 goes at the end.

Your interpretation is correct. But the command is buggy. Let's take a look at the steps you listed and lay out all the gory details.

  1. < infile redirects stdin from infile. This means when ./a.out reads from stdin it will read from the file.

  2. 2>&1 redirects stderr to wherever stdout is currently pointing. Typically stdout will be the terminal and so this makes stderr also write to the terminal. But stderr usually writes to the terminal by default, so this is probably a mistake. I'll explain further below.

  3. > outfile redirects stdout to outfile. When ./a.out writes to stdout it will write to the file.

The net effect is that the program reads from infile, writes its standard output to outfile, and writes errors to the terminal.

If you follow those steps along carefully you might be confused by step 2, because 2>&1 ended up redirecting stderr to where it was already pointing. It is very likely that whoever wrote this got the order of redirections mixed up and meant to write this:

# Fixed redirection order.
./a.out < infile > outfile 2>&1

Here steps 2 and 3 are swapped.

  1. > outfile redirects stdout to outfile. When ./a.out writes to stdout it will write to the file. No change here.

  2. 2>&1 redirects stderr to wherever stdout is currently pointing, which is outfile. All output is now redirected to outfile.

In this version both stdout and stderr are redirected to outfile. Everything is captured, both regular output and errors. That's probably what was intended, agreed?

If you haven't seen this before it may look backwards. Why is 2>&1 at the end? The key insight is that when we say 2>&1 "redirects stderr to stdout", we don't mean that stderr will now and forever point to stdout. We mean that stderr will point to wherever stdout currently points. If we redirect stderr to stdout but then redirect stdout somewhere else, stderr continues pointing to the previous location.

That's why 2>&1 goes at the end.

  • Related