Treating Streams Like Files
Streams in Linux, like almost everything else, are treated as if they were files. You can read text from a file and write text to a file. Both actions contain a data stream. The concept of treating a data stream as a file is not too difficult.
Each file associated with a process is assigned a unique number to identify it. This is called a file descriptor. When an action needs to be performed on a file, the file descriptor is used to identify the file.
These values are always used for
stdout and [1
- 0 : stdin
- 1 : stdout
- 2 : stderr
Responding to pipes and redirects
A common technique is to convey a simplified version of the topic. For example, in the grammar we are told that the rule is "I am before E, except for C.". In fact, there are more exceptions than cases that obey this rule.
Similarly, when speaking of
stderr it is useful to find out the accepted axiom that a process neither knows nor cares where his three standard streams end. Should it be important to a process if its output is sent to the terminal or redirected to a file? Can it even determine if his input comes from the keyboard or is passed into it by another process?
In fact, a process knows, or at least knows, whether to select an exam, and its behavior may change accordingly if the software author adds that functionality.
We can easily recognize this change in behavior. Try these two commands:
ls | cat
ls behaves differently when its output (
stdout ) is redirected to another command. It is
ls that switches to a single column output, it is not a conversion done by
cat . And
ls does the same if its output is redirected:
cat capture.txt  cat capture.txt in a terminal window "width =" 646 "height =" 292 "src =" /pagespeed_static/1.JiBnMqyl6S.gif "onload =" pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon (this); "onerror =" this.onerror = null ; pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon (this); "/>
Redirecting stdout and stderr
Staging error messages through a dedicated stream is an advantage, which means we are issuing a command (
stdout) can be redirected to a file and continue to display all error messages (
stderr) in the terminal window.You can respond to the errors that occurred if necessary, and also prevent the error messages from contaminating the file into the
stdoutumgel was set.
Enter the following text into an editor and save it to a file called error.sh.#! / bin / bash echo "About to try to access a file that does not exist" cat bad-filename.txt
Make the script executable with the following command:chmod + x error.sh
The first line of the script prints the
stdoutto the terminal window next] Stream. The second line attempts to access a file that does not exist. This generates an error message that is transmitted via
Run the script with the following command:./ error.sh
We can see that both output streams,
stderrwere displayed in the terminal windows.
Let's try to redirect the output to a file:./ error.sh> capture.txt
The error message sent via
stderrwill continue to be sent to the terminal window. We can check the contents of the file to see if the output of
stdouthas been included in the file.cat capture.txt
 The output of
stdinwas redirected to the file as expected.
>redirect symbol works by default with
stdout. You can use one of the numeric file descriptors to specify which default output stream you want to redirect.
To explicitly redirect
stdoutuse this redirect directive:1>
For explicit redirection
stderruse this redirection directive:2>
Let's try again, and this time we'll use
2>:./ error .sh 2> capture.txt
The error message is redirected and the
echomessage is sent to the terminal window:
Let's see what's in the capture.txt file.  cat capture.txt
stderris as expected in capture.txt.
redirect stdout and stderr
Certainly if we use either
stderrin one On the other hand, should we be able to redirect both into two separate files at the same time?
Yes, we can. This command directs
stdoutto a file named capture.txt and
stderrto a file named error.txt../ error.sh 1> capture.txt 2> error .txt
Since both Output streams – standard output and standard errors – are redirected to files. No output is visible in the terminal window. We return to the prompt as if nothing had happened.
Let's check the contents of each file:cat capture. txtcat error.txt
Redirecting stdout and stderr to the same file
That's fine, we have Each of the standard output streams has been moved to its own dedicated file. The only other combination we can do is to send both
stderrto the same file.
We can do this with the following command:./ error. sh> capture.txt 2 &> 1
Let's resolve that.
- ./ error.sh : Starts the script file error.sh.
- > capture.txt : directs the
stdoutstreaming to the capture.txt file.
>stands as an abbreviation for
- 2> & 1 : Uses the &> redirect statement. Use this directive to tell the shell to send a stream to the same destination as another stream. In this case, "Stream 2
stderrwill redirect to the same destination to which Stream 1
stdoutwill be redirected."
No output is visible. That's encouraging.
Let's look at the capture.txt file and see what's inside it.
Both the streams
stderr were merged into one redirected only destination file.
Output a redirected and tacitly dropped stream, redirect the output to
/ dev / null .
Detecting Redirection Within a Script
We've explained how a command can detect if any of the streams exist is redirected and can change its behavior accordingly. Can we do this in our own scripts? Yes we can. And it's very easy to understand and apply.
Enter the following text in an editor and save as input.sh.
#! / Bin / bash if [ -t 0 ]; then echo stdin comes from keyboard otherwise echo stdin comes from a pipe or a file fi
Use the following command to make it executable:
chmod + x input.sh
The clever part is the test in square brackets. The option
-t (terminal) returns true (0) if the file associated with the file descriptor exits in the terminal window. We have used the file descriptor 0 as an argument for the test representing
stdin is connected to a terminal window, the test will prove to be true. If
stdin is associated with a file or pipe, the test will fail.
You can use any text file to generate input to the script. Here we use a file called dummy.txt.
./ input.sh <dummy.txt
<img class = "No full-size alignment wp-image-436383" data-pagespeed-lazy-src = "https://www.howtogeek.com/ wp-content / uploads / 2019/08 / x26.png.pagespeed.gp + jp + jw + pj + ws + js + rj + rp + rw + ri + cp + md ic.KS7TuufRTP.png "alt =". / input.sh < dummy.txt in a terminal window" width="646" height="57" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);"/>
The output shows that the script recognizes that the input is not from a keyboard but from a file, so you can vary the behavior of your script.
That was with a file redirection, let's try a pipe.
cat dummy.txt |. /Input.sh[19659035[19459061<catdummytxt|/inputshineintheterminalwindow" width="646" height="57" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);"/>  The script recognizes that its input is directed into the script, or more precisely, it recognizes again that the stream
stdinis not connected to a terminal window.
Let's not run the script with pipes or redirects../ input.sh
stdinstream is connected to the terminal window, and the script reports this accordingly.
To verify the same with the output stream, we need a new script. Type the following in an editor and save it as output.sh.#! / Bin / bash if [-t 1]; then echo stdout calls the terminal window otherwise echo stdout is redirected or forwarded fi
Use the following command to make it executable:chmod + x input.sh
The only significant change to this script is the test in square brackets. We use the numeral 1 to represent the file descriptor for
Let's try it. We pass the issue on
cat../ output | Cat
The script detects that its output does not lead directly to a terminal window.
The script can also be tested by redirecting the output to a file../ output.sh> capture.txt
There is no output. In the terminal window we return unnoticed to the command prompt. As expected.
In the capture.txt file you can read what has been captured. Use the following command.cat capture.sh
The simple test in our script recognizes again that the standard output
existsStream is not directly attached sent a terminal window.
If the script is executed without pipes or redirections, it should be noted that
stdoutis sent directly to the terminal window.  ./ output.sh
And that's exactly what we see.
 Awareness streams
If you know whether your scripts are connected or redirected to the terminal window or a pipe, you can adjust their behavior accordingly.
Logging and diagnostic output can be more or less less detailed, depending on whether it is a screen or a file. Error messages can be logged in a file other than the normal program output.
As usual, more knowledge brings more options.