bodn19888
bodn19888

Reputation: 177

Order of events in Bash shell redirection of standard output and error to the same file

I want to ask a question about redirecting standard output and error to the same file using a Bash Shell.

I am a beginner in the Linux Command Prompt and am reading a book titled "The Linux Command Line" by William E. Shotts. Jr.

In a section on redirection, he states that to redirect standard output and error to the same file, the following command is written:

ls -l /bin/usr > ls-output.txt 2>&1

From what I understand, the /bin/usr directory does not exist, so an error is thrown up and is sent to the standard error file. The output of the command ls -l /bin/usr is redirected to a text file ls-output.txt and the standard error is redirected to standard output with 2>&1.

I'm confused here on two aspects:

  1. Firstly, the order of events. By my intuition, since I thought commands are executed in an L-R fashion (Left-to-Right), it appears that the redirection of the ls command takes place first towards ls-output.txt before the redirection of the standard error stream (2) to the standard output stream (1).

  2. The use of the ampersand. I understand from a Google search that if & is placed at the end of a command, it means that other commands can be input before the initial command is executed - which has application when the initial command is coupled with a timer. I believe that the ampersand here implies that the & means that we are redirecting to a file descriptor and not a file name named 1, although I'm unsure whether this is correct.

Overall, I have two questions:

  1. What is the order of execution of the command above?
  2. Am I correct in the function of the ampersand &? If not, what function does it serve?

Upvotes: 1

Views: 686

Answers (2)

Gordon Davisson
Gordon Davisson

Reputation: 125928

Let me expand on aspect 1, the order of events. It's a mistake to think of things happening in strict left-to-right order; command processing and execution happens in phases and while each phase is (generally) done left-to-right, each phase will (again, generally) be finished before the next one starts.

In this case, the relevant phases are:

  1. The shell parses the command line (this is actually several phases itself).
  2. The shell processes I/O redirections (from left to right).
  3. The shell executes the command (with all redirects already in place).

One important consequence of this is that you can't redirect output back to a file you're using as input for the command. For example, if you tried to sort a file with sort file.txt >file.txt, the shell would open file.txt and empty it to get it ready for its new contents before sort has a chance to read from it. Result: an empty file.

A less important consequence is that if there's an error in a redirect, it'll prevent the command from even being started. If you run nosuchcommand <nosuchfile, bash will print an error about nosuchfile not existing before it even notices that nosuchcommand doesn't exist either.

Upvotes: 2

SpiderPig1297
SpiderPig1297

Reputation: 335

Linux has three default data streams - stdin (0), stdout (1) and stderr (2).

  • stdin, or "standard in", is used for reading data from the user.
  • stdout, or "standard out", is used for "usual" output.
  • stderr, or "standard error" is used for errors.

The character > allows you to redirect your command's output into one of the streams mentioned above, or in to a file.

When you run the command ls -l /bin/usr > ls-output.txt 2>&1, you actually ask from your system two things:

  1. Redirect the stdout of the command into the file ls-output.txt.
  2. Redirect the stderr of the command into the data stream whose number is 1, which is the stdout stream.

Actually, using > by itself is equivalent to 1>, meaning that you redirect all output from data stream no. 1.

The & char tells your system that you are going to redirect the output into a data stream, instead of a file. Omitting this character will result in your stderr written to a file named 1.

It is important to note that the character & has more roles in Linux, like running commands in the background or concatenating commands (using &&), but it is completely different.

Best regards.

Upvotes: 3

Related Questions