A command that was seemingly created to work in tandem with a pipe is tee. The description on the man page should tell most of the story:
So, in essence, sending something to the stdin of tee (via a pipe!) allows us to save that output to both your Terminal and a file at the same time.
This is often most useful when using interactive commands; it allows you to follow the output live, but also write it to a (log) file for later review. Updating a system provides a good example for the use case of tee:
sudo apt upgrade -y | tee /tmp/upgrade.log
We can make it even better by sending all output to tee, including stderr:
sudo apt upgrade -y |& tee /tmp/upgrade.log
The output will look something like this:
reader@ubuntu:~/scripts/chapter_12$ sudo apt upgrade -y |& tee /tmp/upgrade.log
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
<SNIPPED>
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
reader@ubuntu:~/scripts/chapter_12$ cat /tmp/upgrade.log
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
<SNIPPED>
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
The first line of both the Terminal output and the log file is a WARNING which is sent to stderr; if you used | instead of |&, that would not have been written to the log file, only on the screen. If you use |& as advised, you will see that the output on your screen and the contents of the file are a perfect match.
By default, tee overwrites the destination file. Like all forms of redirection, tee also has a way to append instead of overwrite: the --append (-a) flag. In our experience, this is often a prudent choice, not dissimilar to |&.