1. Introduction
We sometimes run into instances where we would like to save the output of our commands. Being able to write to a file directly from the terminal is one of the significant features Linux offers. This makes it very easy to produce files that can be further processed. Writing to files also comes in handy when we are running scripts. Our scripts need a place to send their data, store it and also save the errors it produces during its execution.
In this tutorial, we’ll look at the various ways to utilize the feature of writing to a file directly from a Bash terminal. We’ll first look at how to save information to a file instead of sending it to the terminal and how to send output to both the terminal and a file. Later, we’ll write a small script that does both.
2. The Standard Input/Output Redirection
Linux bash has different options for receiving input from a command and saving output from a command. One of the most used ways is input/output redirection. Redirection is the process by which we can cause the shell to alter where the standard input of command comes from and where the standard output goes.
Redirection has three data streams:
The standard input (stdin) – this is the place a program gets its information from. By default, the shell receives standard input from the keyboard. We can alter this default behavior such that the program receives data from a different source, like a file. < operator denotes standard input redirection. In this tutorial, we won’t focus on stdin.
The standard output (stdout) – is the place to which a program sends the information it has produced. Primarily, the terminal receives the output. > operator denotes standard output. When we use output redirection, we should be careful as it can destroy a file. If the file exists, the shell will overwrite it and destroy its content. If not, it creates the file.
The standard error (stderr) – when we run commands, we have the possibility of running into errors. These errors can be sent to the terminal or written into a separate file. Alternatively, we can also refer to stderr as error messages*.*
2.1. Examples of Standard Output and Standard Error Redirection
To redirect standard output, we use the > operator after the command and type a filename after the symbol. When we use stdout, we can also specify the directory we would like to save the file into by including the path of the filename as shown below:
$ uname -a > compinfo.txt
Earlier, we had mentioned that output redirection could damage a file. This is avoidable if we use the >> symbol to append to a file if the file already exists:
$ date >> compinfo.txt
We can prevent the files from being overwritten by enabling the noclobber:
$ set -o noclobber
When we run a command and encounter an error during execution, we can send that error to a file by using stderr. To redirect stderr, we use the stdout operator with a 2 before it:
$ fdisk -l 2> errors.txt
To send stderr and stdout to the same file, we use &>.
3. Other Commands for Writing to File
Apart from the standard output and standard error, we have the tee command. This command reads from standard input to display to the screen and write to a file or multiple files. If we use the -a flag with the tee, it appends.
We can prevent tee from displaying output on the terminal by sending the standard output to /dev/null:
$ uname -a | tee systeminfo.txt
$ date | tee systeminfo.txt systeminfo2.txt
$ date | tee -a systeminfo.txt
$ uname -a | tee systeminfo.txt > /dev/null
4. Writing to a File From a Script
Usually, the scripts we write perform different functions. Some of these functions are so critical that we wouldn’t want everyone to be able to view the output produced. During execution, these scripts may also run into errors that may leak confidential information. Therefore, it is better if we have a place defined for such errors to be sent to instead of the terminal.
Let us now write a simple script that generates the computer’s system information and sends it to a file. We’ll also specify a separate file for errors. Let’s create a file named sysinfo.sh and type the following:
#!/usr/bin/bash
mkdir info;
( date; echo ; uname -a; echo ; free -h;fdisk -l; echo ; ) > info/systeminfo.txt 2> info/systeminfoerror.txt;
( echo -e "\n DISK INFORMATION. \n"; sudo fdisk -l;echo ; ) >> info/systeminfo.txt;
lscpu | tee info/cpu_info_1.txt #output sent to both screen and file
lscpu | tee info/cpuinfo_2.txt > /dev/null; #no output is sent to screen
echo -e "\t\t\t Located in:$HOME/info/ \t\t\t";
If we don’t want the output tee will send to the screen, we can redirect the standard output to /dev/null. Also*,* to group commands, we can either enclose them in parentheses or curly braces. This enables us to execute them as a single unit. Lastly, let us save the file, run it and see the output:
$ bash sysinfo.sh
$ ls info/
cpu_info_1.txt cpuinfo_2.txt systeminfoerror.txt systeminfo.txt
5. Conclusion
In conclusion, being able to write to a file from the terminal or through a script is of great essence. We can use standard output and standard error redirection to write to files. To add on, we can also use the tee command to write to a file and display output on the terminal.