- How to redirect output to a file and stdout
- 11 Answers 11
- How to redirect shell command output
- Training & certification
- Types of output
- How to redirect shell output
- 1. Redirect STDOUT
- 2. Redirect STDERR
- 3. Send STDOUT and STDERR to the same file
- 4. Redirect output, but append the file
- 5. Redirect to another process or to nowhere
- 6. Use redirection in a script
- Great Linux resources
- Wrap up
How to redirect output to a file and stdout
In bash, calling foo would display any output from that command on the stdout. Calling foo > output would redirect any output from that command to the file specified (in this case ‘output’). Is there a way to redirect output to a file and have it display on stdout?
If someone just ended up here looking for capturing error output to file, take a look at — unix.stackexchange.com/questions/132511/…
A note on terminology: when you execute foo > output the data is written to stdout and stdout is the file named output . That is, writing to the file is writing to stdout. You are asking if it is possible to write both to stdout and to the terminal.
@WilliamPursell I’m not sure your clarification improves things 🙂 How about this: OP is asking if it’s possible to direct the called program’s stdout to both a file and the calling program’s stdout (the latter being the stdout that the called program would inherit if nothing special were done; i.e. the terminal, if the calling program is an interactive bash session). And maybe they also want to direct the called program’s stderr similarly («any output from that command» might be reasonably interpreted to mean including stderr).
If we have multiple commands that want to pipe outputs, use ( ) . For example (echo hello; echo world) | tee output.txt
11 Answers 11
The command you want is named tee :
For example, if you only care about stdout:
If you want to include stderr, do:
program [arguments. ] 2>&1 | tee outfile
2>&1 redirects channel 2 (stderr/standard error) into channel 1 (stdout/standard output), such that both is written as stdout. It is also directed to the given output file as of the tee command.
Furthermore, if you want to append to the log file, use tee -a as:
program [arguments. ] 2>&1 | tee -a outfile
If OP wants «all output» to be redirected, you’ll also need to grab stderr: «ls -lR / 2>&1 | tee output.file»
@evanmcdonnal The answer is not wrong, it just may not be specific enough, or complete depending on your requirements. There certainly are conditions where you might not want stderr as part of the output being saved to a file. When I answered this 5 years ago I assumed that the OP only wanted stdout, since he mentioned stdout in the subject of the post.
Ah sorry, I might have been a little confused. When I tried it I just got no output, perhaps it was all going to stderr.
Use -a argument on tee to append content to output.file , instead of overwriting it: ls -lR / | tee -a output.file
If you’re using $? afterwards it will return the status code of tee , which is probably not what you want. Instead, you can use $ .
$ program [arguments. ] 2>&1 | tee outfile
2>&1 dumps the stderr and stdout streams. tee outfile takes the stream it gets and writes it to the screen and to the file «outfile».
This is probably what most people are looking for. The likely situation is some program or script is working hard for a long time and producing a lot of output. The user wants to check it periodically for progress, but also wants the output written to a file.
The problem (especially when mixing stdout and stderr streams) is that there is reliance on the streams being flushed by the program. If, for example, all the writes to stdout are not flushed, but all the writes to stderr are flushed, then they’ll end up out of chronological order in the output file and on the screen.
It’s also bad if the program only outputs 1 or 2 lines every few minutes to report progress. In such a case, if the output was not flushed by the program, the user wouldn’t even see any output on the screen for hours, because none of it would get pushed through the pipe for hours.
Update: The program unbuffer , part of the expect package, will solve the buffering problem. This will cause stdout and stderr to write to the screen and file immediately and keep them in sync when being combined and redirected to tee . E.g.:
$ unbuffer program [arguments. ] 2>&1 | tee outfile
How to redirect shell command output
Learn how to process the output of shell commands within a script and send it to files, devices, or other commands or scripts.
Shell scripts provide a very powerful feature: the ability to redirect the output from commands and scripts and send it to files, devices, or even as input to other commands or scripts.
Training & certification
This article focuses on command and script output.
Types of output
Commands and scripts in a shell can generate two basic types of outputs:
- STDOUT: The normal output from a command/script (file descriptor 1)
- STDERR: The error output from a command/script (file descriptor 2)
By default, STDOUT and STDERR are sent to your terminal’s screen.
In terms of input, STDIN by default reads input from the keyboard (file descriptor 0). A file descriptor is a unique identifier for a file or other I/O resource.
How to redirect shell output
There are multiple ways to redirect output from shell scripts and commands.
1. Redirect STDOUT
For the following examples, I will use this simple set of files:
$ls -la file* -rw-r--r--. 1 admin2 admin2 7 Mar 27 15:34 file1.txt -rw-r--r--. 1 admin2 admin2 10 Mar 27 15:34 file2.txt -rw-r--r--. 1 admin2 admin2 13 Mar 27 15:34 file3.txt
I’m running a simple ls commands to illustrate STDOUT vs. STDERR, but the same principle applies to most of the commands you execute from a shell.
I can redirect the standard output to a file using ls file* > my_stdout.txt :
$ls file* > my_stdout.txt $ cat my_stdout.txt file1.txt file2.txt file3.txt
Next, I run a similar command, but with a 1 before > . Redirecting using the > signal is the same as using 1> to do so: I’m telling the shell to redirect the STDOUT to that file. If I omit the file descriptor, STDOUT is used by default. I can prove this by running the sdiff command to show the output of both commands side by side:
$ls file* 1> my_other_stdout.txt $sdiff my_stdout.txt my_other_stdout.txt file1.txt file1.txt file2.txt file2.txt file3.txt file3.txt
As you can see, both outputs have the same content.
2. Redirect STDERR
Now, what is special about STDERR? To demonstrate, I will introduce an error condition to the previous example with ls file* non-existing-file* > my_normal_output.txt :
Here are some observations from the above test:
- The output about the existing files is sent correctly to the destination file.
- The error (which displays when I try to list something that does not exist) is sent to the screen. This is the default place errors are sent unless you redirect them.
Next, I’ll redirect the error output by referencing file descriptor 2 explicitly with ls file* non-existing-file* > my_normal_output.txt 2> my_error_output.txt:
- The ls command does not display the error message on the screen like before.
- The normal output contains what I expect.
- The error message is sent to the my_error_output.txt file.
3. Send STDOUT and STDERR to the same file
Another common situation is to send both STDOUT and STDERR to the same file:
$ls file* non-existing-file* > my_consolidated_output.txt 2>&1 $ cat my_consolidated_output.txt ls: cannot access 'non-existing-file*': No such file or directory file1.txt file2.txt file3.txt
In this example, all output (normal and error) is sent to the same file.
The 2>&1 construction means «send the STDERR to the same place you are sending the STDOUT.»
4. Redirect output, but append the file
In all the previous examples, whenever I redirected some output, I used a single > , which means «send something to this file, and start the file from scratch.» As a result, if the destination file exists, it is overwritten.
If I want to append to an existing file, I need to use >> . If the file doesn’t already exist, it will be created:
$echo "Adding stuff to the end of a file" >> my_output.txt $cat my_output.txt file1.txt file2.txt file3.txt Adding stuff to the end of a file
5. Redirect to another process or to nowhere
The examples above cover redirecting output to a file, but you can also redirect outputs to other processes or dev/null .
Sending output to other processes is one of the most powerful features of a shell. For this task, use the | (pipe) symbol, which sends the output from one command to the input of the next command:
ps -ef | grep chrome | grep -v grep | wc -l 21
The above example lists my processes, filters any that contain the string chrome, ignores the line about my grep command, and counts the resulting lines. If I want to send the output to a file, I add > and a file name to the end of the chain.
Finally, here is an example where I want to ignore one of the outputs, the STDERR:
$tar cvf my_files.tar file* more-non-existing* file1.txt file2.txt file3.txt tar: more-non-existing*: Cannot stat: No such file or directory tar: Exiting with failure status due to previous errors
Because the tar command did not find any files with names starting with more-non-existing , some error messages display at the end.
Suppose I create some scripts and don’t care about seeing or capturing these errors (I know, in real life, you should prevent and handle the errors, not just ignore them):
$tar cvf my_files.tar file* more-non-existing* 2> /dev/null file1.txt file2.txt file3.txt
The /dev/null is a special device file that is like a «black hole»: What you send there just disappears.
6. Use redirection in a script
=== SUMMARY OF INVESTIGATION OF chrome === Date/Time of the execution: 2022-03-25 18:05:50 Number of processes found.: 5 PIDs: 1245475 1249558 1316941 1382460 1384452
Great Linux resources
This very simple script does the following:
- Line 3: Executes a command in the operating system and saves to the variable DATE_TIME.
- Line 6: Runs the ps command and redirects to grep and to a file.
- Instead of sending the output to a file, I could send it to a variable (as in line 3), but in this case, I want to run other actions using the same output, so I capture it. In a more realistic situation, having the file could also be useful during development or troubleshooting, so I can more easily investigate what the command generates.
Wrap up
Those were some examples of redirecting STDOUT and STDERR. Putting all this together, you realize how powerful redirection can be. By chaining individual commands, manipulating their output, and using the result as the input for the next command, you can perform tasks that otherwise could require you to develop a script or program. You could also incorporate the technique into other scripts, using everything as building blocks.