0

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?
bodn19888
  • 167
  • 10

2 Answers2

2

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.

SpiderPig1297
  • 305
  • 1
  • 8
  • I had a reflection - the redirection happens right when the command has been read fully first i.e. after the redirection of the standard stream? so after `2>&1` will the command actually be executed? – bodn19888 Sep 29 '20 at 22:33
  • It is bit more complicated than that. What redirection actually does is replacing the process' file descriptors with those specified by the command. For example, if I have a program which continuously writes "Hello, World" to `stdout`, redirecting its output to a file using `>` will cause the program to write to the file instead to the screen. The program will still run forever, but with its output written to a file. So, for your question - redirection doesn't affect the execution order of a binary, it just changes its file descriptors. Note though that piping are completely different thing. – SpiderPig1297 Sep 29 '20 at 22:42
  • many thanks! I'll give you an upvote and a tick for a great explanation! And welcome to StackOverflow! – bodn19888 Sep 29 '20 at 22:45
  • Thanks! Feel free to ask more questions if you have :) – SpiderPig1297 Sep 29 '20 at 22:46
1

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.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151