Direct output from a command to a file including the original command, AND print in terminal
That's tee
you're searching for.
ls -l | tee outfile
prints the output of ls -l
to stdout (i.e. the terminal) and saves it in the file outfile
at the same time. But: It doesn't write the command name neither to stdout nor to the file. To achieve that, just echo
the command name before running the command and pipe both outputs to tee
:
( echo "ls -l" && ls -l ) | tee outfile
That's cumbersome to type, so why not define a function?
both(){ ( echo "$@" && "$@" ) | tee outfile ;}
After that you can just run
both ls -l
to get the desired result. Put the function in your ~/.bashrc
to have it defined in every new terminal.
If you want to be able to specify the output file as the first argument like in
both output ls -l
instead make it:
both(){ ( echo "${@:2}" && "${@:2}" ) | tee "$1" ;}
If you don't want the output file to be overwritten but rather append to it, add the -a
option to tee
.
You could make use of the script
command which will make a typescript file of everything printed to your terminal. It creates a forked shells and will record everything until that shell is exited.
$ script my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
Script done on Tue 28 Nov 2017 09:46:27 AM UTC
Then if I cat my_output
I get the same output:
$ cat my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
exit
Script done on Tue 28 Nov 2017 09:46:27 AM UTC
You can use the debugging function of the shell together with tee
:
( set -x; command1 args...; command2 args ) 2>&1 | tee output.log
( ... )
starts a sub-shell which allows you to “collect” the output streams of all commands executed within the sub-shell. It also contains the effect of theset
command below to this sub-shell.set -x
enables thex
shell option which prints all commands that the shell runs to the standard error stream before running them.2>&1
redirects stream 2 (standard error) to stream 1 (standard output).|
redirects the the standard output stream of the left command to the standard input stream of the right command.tee FILE
copies the standard input stream to the fileFILE
and to standard output.
If your command sequence is already in a script file it would make more sense to run it like this:
bash -x /path/to/script args... 2>&1 | tee output.log