In openSUSE, we often have an opportunity to use terminal commands for various purposes including their usage within bash scripts. Please remember that in most cases, terminal commands are always run using lower case file names. When redirection to those file names is used in a bash script, we may have a desire to control how the resulting command text is displayed. When terminal commands are executed, they most often use a standard text output, which is called STDOUT and they can also display error messages sent to STDERR. And when terminal commands are input, they can be received from STDIN. In terminal and in a bash script, these three locations can be referenced to by a single digit integer number called a file descripter as in the following example:
STDIN = 0
STDOUT = 1
STDERR = 2
[size=3][FONT=Liberation Serif]In terminal or our bash script, we use the greater-than symbol > to send out text and we can use the less-than symbol < to receive text from a different source from say a text file and not the keyboard. When sending text to (i.e., >) STDOUT or STDERR as a target, or receiving text from STDIN (i.e. <) we must add the ampersand in front of the number to discern the number from a file name (i.e., &0, &1 or &2). When selecting one of the three devices of 0,1 & 2 as a source, we must immediately proceed the number using a redirection symbol (i.e., 0>,1> or 2>) after it so as to not be taken for a file name as well. Not all possible combinations make sense and so are not normally used. In addition to the three standard devices, we can send output to a device, such as /dev/null, because we don’t want to see or save the command result, or to filename.ext, because we want to save the result of the command for later usage.[/FONT]
> = send text to STD destination, device or file. If file exists, its contents will be over written.
>> = to append text to a destination file at the end and will create the file if it does not exist.
< = to receive text from a device or file.
& = Ampersand added to STD??? number to discern it from a filename destination.
| = Piping symbol to send output results from one command into another command.
~ = Tilde symbol to represent your /home/username folder in our examples.
Now what we need are some examples of using redirection. Consider the lowly terminal dir command:
dir /etc
This will produce a large text listing. We could add the terminal command less to the end to browse the text (q=Quit and h=Help while using less):
dir /etc | less
But what if instead, we want to save the result of the dir command into a file? Consider these commands:
dir > myfile.txt
cat myfile.txt
.. your file contents shown here ...
rm myfile.txt
In the first command, we send a directory listing of the default folder into the file we called myfile.txt while nothing except out terminal command was displayed. The next command, called cat, displayed the contents of the text file called myfile.txt, that we had saved using redirection. Then finally, we removed the text file called myfile.txt as it is no longer needed in our example. Imagine now that using redirection, you could send the output of any terminal command to a text file to save its results if we wanted to do so. Lets us extend the example by appending the results of two command together.
dir ~/Downloads > myfile.txt
dir ~/Documents >> myfile.txt
cat myfile.txt
.. both file contents shown here ...
rm myfile.txt
This adds a second directory command and appends the output to the first using the >> redirect option. We can see the result using the cat command and remove the results when we are done with it. Now what if we want to perform a command, but we do not want to see the results at all. Consider this command:
dir /etc > /dev/null
We perform the same directory command as we did in the first example, but we are sending the text results of that command to the device called /dev/null, which then shows no text results of our dir command in our terminal display. Consider this does not seem to be useful at first, but there are hundreds of terminal commands you can use in a bash script and perhaps you don’t want what is sent to the screen to mess up your bash script text display as your commands are executed and the /dev/null target is helpful in that task. Terminal commands can produce error messages when run and perhaps they occur in normal execution of your bash script. Or, perhaps you want to capture all errors and save them to a log or text file for viewing later. Consider the following command:
dir /blackhole
If we can assume you don’t have a folder called blackhole in your default folder where we are playing with terminal commands, you should get the following response:
ls: cannot access /blackhole: No such file or directory
The ls command is complaining that the file or folder name of /blackhole can no be found. It is ls complaining because the dir terminal binary file just uses ls to give us our file and folder display. If we did not want to see that error command, we could use the following command:
dir /blackhole 2> /dev/null
Now when you execute this command, you get no text output of your error message (only) in terminal at all. Standard, non-error text, will still get displayed. Maybe that is what you prefer to have happen as your bash script is run? Now, lets consider the next command:
dir /blackhole > myfile.txt
ls: cannot access /blackhole: No such file or directory
cat myfile.txt
.. nothing is displayed here ...
rm myfile.txt
Now I thought the redirection command should have sent ALL of the text output to my text file called myfile.txt, but instead what we got was an error message and out text file myfile.txt seems to be blank. Well now you can see that while the normal result of our command is sent to STDOUT, our error message is being sent to STDERR instead. Now, lets try our terminal commands again:
dir /blackhole > myfile.txt 2>&1
cat myfile.txt
ls: cannot access /blackhole: No such file or directory
rm myfile.txt
Now what if we want ALL text, both standard and error text to not be displayed or saved anywhere? We actually see two kinds of redirection taking place here. We want to send all error messages to STDOUT and we want to send STDOUT out to a text file called myfile.txt. Consider using the following command setup then:
dir /etc > /dev/null 2>&1
This command also includes two kinds of redirection and we want to send all output, STDOUT and STDERR to the null device so as to not be seen by anyone. You can also write this as the command:
[/size]
[FONT=Liberation Serif]dir /etc &>/dev/null[/FONT]
But I prefer to write as shown first. Do consider that if you send error messages to null, they are gone for ever. I tend to add the commands [size=4]"[/size][FONT=Liberation Serif]> /dev/null 2>&1" or “[/FONT][size=4][FONT=Liberation Serif]2> /dev/null” at the end of my bash script writing cycle as the absence of error message can make it hard to trouble shoot your bash script. Once you are done though it can help tidy up that text output for other users to see.[/FONT]
This concludes my first attempt at describing and demonstrating the use of redirection in terminal and for use in a bash script. I would love to hear any command you would like to make.
Thank You,
[/size]