LFCS 28 ๐ง tee โ Splitting Output
The pipe sends the output of one command to the input of the next, and the output is consumed. The command | grep 'pattern' sends the output to the grep, and the grep prints the matching lines. But the original output is gone: the command‘s output was piped and not saved. The tee solves the problem. It reads the standard input and writes to both the standard output and one or more files. The command | tee output.txt saves the output to the file and continues the pipeline. The tee is the T-splitter, and it is the way to capture the intermediate output while the pipeline continues. The LFCS exam tests it as part of the “Use streams, pipes, and redirects” objective.
The tee is the standard tool for the logging and the debugging. The make 2>&1 | tee build.log captures the build output while displaying it. The command | tee output.txt | grep 'error' saves the full output and filters the errors. The tee -a appends to the file instead of the truncating. The tee writes to the multiple files: the command | tee file1 file2 writes to the both. The tee is the simple, and the applications are the many.
The tee has the specific behavior. It reads from the standard input and writes to the standard output and the files. The output is the unbuffered by default, and the --line-buffered makes it the line-buffered. The -i ignores the SIGINT, and the -p diagnoses the write errors. The tee returns the exit status of the failed file write, and the pipeline continues. The tee is the complement to the pipe: the pipe connects, and the tee branches.
This chapter covers three areas. First, why the tee exists โ the capture problem and the split. Second, the syntax and the options โ the -a, the -i, the -p, the --output-error, and the --line-buffered. Third, the common patterns โ the logging, the debugging, the multiple files, the privileged writes, and the pipeline inspection. The chapter ends with a complete example session, a quick reference, best practices, common pitfalls, real-world examples, and diagrams showing the tee flow.
Key point: The tee reads the standard input and writes to both the standard output and the files. The command | tee output.txt saves the output and continues the pipeline. The -a appends, the -i ignores the SIGINT, and the --line-buffered makes the output the line-buffered. The tee is the T-splitter, and it is the way to capture the intermediate output while the pipeline continues.
Why tee exists
The capture problem. The pipe consumes the output. The command | grep 'pattern' sends the output to the grep, and the original output is not saved. The tee captures the output while the pipeline continues: the command | tee output.txt | grep 'pattern' saves the full output to the file and the filters the lines. The tee is the branch, and the pipe is the straight line.
The logging problem. The scripts and the builds produce the output that should be the logged. The make | tee build.log captures the build output and the displays it. The tee -a build.log appends to the log across the multiple runs. The tee is the logging, and the pipe is the display.
The debugging problem. The pipeline hides the intermediate output. The command1 | command2 | command3 shows the final output, and the intermediate is the invisible. The tee inserts the inspection point: the command1 | tee step1.txt | command2 | tee step2.txt | command3 saves the each stage. The tee is the debugging tool.
The privileged-write problem. The sudo command > /root/file.txt fails, because the redirection runs in the user’s shell, not the sudo. The command | sudo tee /root/file.txt works, because the tee runs with the sudo and the writes to the file. The tee is the privileged write.
The multiple-destination problem. The output should go to the multiple places: the display, the file, and the another command. The command | tee file1 file2 | grep 'pattern' writes to the both files and the filters. The tee is the fan-out.
The trade-off. The tee adds the process to the pipeline, and the process has the overhead. The tee writes the output twice, and the disk I/O is the doubled. The tee with the large output and the slow disk is the bottleneck. The trade-off is between the capture and the performance.
a. The basic tee syntax
The tee reads the standard input and writes to the standard output and the files.
command | tee output.txt
command | tee output.txt | grep 'pattern'
command | tee -a output.txt
command | tee file1.txt file2.txt
The command | tee output.txt saves the output and the displays it. The tee is the T-splitter, and the standard output is the vertical bar.
The -a. The -a appends to the file instead of the truncating:
command | tee output.txt
command | tee -a output.txt
The first run truncates, and the second appends. The -a is the log rotation.
The -i. The -i ignores the SIGINT:
command | tee -i output.txt
The -i is the Ctrl+C handling, and it is the important for the long-running.
The -p. The -p diagnoses the write errors:
command | tee -p output.txt
The -p reports the write error on the pipe, and the GNU extension.
The --output-error. The --output-error controls the write-error behavior:
command | tee --output-error=warn output.txt
command | tee --output-error=warn-nopipe output.txt
command | tee --output-error=exit output.txt
The warn is the default, the warn-nopipe ignores the EPIPE, and the exit exits on the error.
The --line-buffered. The --line-buffered makes the output the line-buffered:
command | tee --line-buffered output.txt
The --line-buffered is the important for the live monitoring, and the default is the block-buffered.
b. The common patterns
The logging. The build and the script logging:
make 2>&1 | tee build.log
./deploy.sh 2>&1 | tee deploy.log
command | tee -a /var/log/app.log
The 2>&1 merges the stderr into the stdout, and the tee captures the both.
The pipeline inspection. The debugging of the multi-stage pipeline:
cat data.txt | tee step1.txt | sort | tee step2.txt | uniq -c | tee step3.txt
The each stage is the saved, and the inspection is the easy.
The multiple destinations. The output to the display and the files:
command | tee /tmp/output.txt /var/log/app.log
The tee writes to the both files and the standard output.
The privileged write. The sudo with the tee:
echo 'config' | sudo tee /etc/app/config.conf
echo 'config' | sudo tee -a /etc/app/config.conf
The sudo tee writes to the root-owned file, and the > does not.
The grep with the tee. The capture and the filter:
command | tee full.log | grep 'ERROR'
command | tee full.log | grep -c 'ERROR'
The full.log has the everything, and the grep shows the errors.
The tail with the tee. The live monitoring:
tail -f app.log | tee -a archive.log | grep --line-buffered 'ERROR'
The tail -f follows, the tee archives, and the grep filters with the line-buffered.
The gzip with the tee. The compress and the inspect:
command | tee >(gzip > output.gz) | grep 'pattern'
The >() is the process substitution, and the tee writes to the both.
The tee with the xargs. The intermediate with the arguments:
find . -name '*.log' | tee filelist.txt | xargs -r rm
The filelist.txt has the names, and the xargs removes them.
The password with the tee. The chpasswd:
echo 'user:password' | sudo tee /tmp/pass.txt
sudo chpasswd < /tmp/pass.txt
rm /tmp/pass.txt
The tee writes the password file, and the cleanup is the important.
The tee with the dd. The disk image:
dd if=/dev/sda | tee /dev/stderr | gzip > sda.img.gz
The tee shows the progress on the stderr and the pipes the data to the gzip.
c. The advanced patterns
The process substitution. The tee with the >():
command | tee >(gzip > out.gz) >(wc -l > count.txt) > /dev/null
The tee writes to the multiple process substitutions, and the /dev/null is the standard output discard.
The named pipe. The tee with the mkfifo:
mkfifo pipe1 pipe2
command | tee pipe1 pipe2 &
consumer1 < pipe1 &
consumer2 < pipe2 &
The tee writes to the named pipes, and the consumers read them.
The tee with the sudo. The privileged write:
command | sudo tee /etc/config.conf > /dev/null
The > /dev/null discards the standard output, and the sudo tee writes the file.
The tee with the ssh. The remote logging:
command | tee >(ssh remote 'cat > /var/log/app.log')
The tee writes to the local and the remote.
The tee with the mail. The notification:
command | tee >(mail -s 'The result' user@example.com)
The tee displays and the emails.
The tee with the logger. The syslog:
command | tee >(logger -t myapp)
The tee displays and the logs to the syslog.
The tee with the systemd-cat. The journal:
command | tee >(systemd-cat -t myapp)
The tee displays and the logs to the journal.
The tee with the parallel. The parallel processing:
command | tee >(parallel -j 4 process)
The tee displays and the parallel processes.
The tee with the split. The file splitting:
command | tee >(split -b 1M - prefix_)
The tee displays and the split writes the chunks.
Complete Example Session
# ============================================
# PART 1: THE BASIC TEE
# ============================================
command | tee output.txt
command | tee output.txt | grep 'pattern'
# ============================================
# PART 2: THE APPEND
# ============================================
command | tee output.txt
command | tee -a output.txt
# ============================================
# PART 3: THE MULTIPLE FILES
# ============================================
command | tee file1.txt file2.txt
# ============================================
# PART 4: THE PRIVILEGED WRITE
# ============================================
echo 'config' | sudo tee /etc/app/config.conf
echo 'config' | sudo tee -a /etc/app/config.conf
# ============================================
# PART 5: THE LOGGING
# ============================================
make 2>&1 | tee build.log
./deploy.sh 2>&1 | tee deploy.log
# ============================================
# PART 6: THE PIPELINE INSPECTION
# ============================================
cat data.txt | tee step1.txt | sort | tee step2.txt | uniq -c | tee step3.txt
# ============================================
# PART 7: THE GREP WITH THE TEE
# ============================================
command | tee full.log | grep 'ERROR'
command | tee full.log | grep -c 'ERROR'
# ============================================
# PART 8: THE LINE BUFFERED
# ============================================
tail -f app.log | tee --line-buffered archive.log | grep --line-buffered 'ERROR'
# ============================================
# PART 9: THE PROCESS SUBSTITUTION
# ============================================
command | tee >(gzip > output.gz) | grep 'pattern'
command | tee >(logger -t myapp) > /dev/null
# ============================================
# PART 10: THE LFCS PIPELINE
# ============================================
# Capture the build output while displaying it
make 2>&1 | tee build.log
# Save and filter
command 2>&1 | tee full.log | grep 'ERROR'
# The privileged write
echo 'Setting=value' | sudo tee /etc/app/settings.conf
# The append to the log
command | tee -a /var/log/app.log
# The multi-destination
command | tee /tmp/output.txt /var/log/app.log
# The pipeline inspection
cat data.txt | tee /tmp/step1.txt | sort | tee /tmp/step2.txt | uniq -c
# The live monitoring
tail -f app.log | tee -a archive.log | grep --line-buffered 'ERROR'
# The compress and inspect
command | tee >(gzip > output.gz) | wc -l
# The logger
command | tee >(logger -t myapp) | grep 'pattern'
# The parallel
command | tee >(parallel -j 4 process) | wc -l
The ten parts show the basic tee, the append, the multiple files, the privileged write, the logging, the pipeline inspection, the grep with the tee, the line-buffered, the process substitution, and the LFCS pipeline.
Quick Reference
The tee Options
| The option | The purpose |
|---|---|
-a | The append |
-i | The ignore the SIGINT |
-p | The diagnose the write errors |
--output-error=MODE | The write-error behavior |
--line-buffered | The line-buffered |
--help | The help |
--version | The version |
The --output-error Modes
| The mode | The behavior |
|---|---|
warn | The default; the warn on the write error |
warn-nopipe | The warn except the EPIPE |
exit | The exit on the write error |
exit-nopipe | The exit except the EPIPE |
The Common Patterns
| The pattern | The command |
|---|---|
| The basic capture | command | tee output.txt |
| The append | command | tee -a output.txt |
| The multiple files | command | tee f1 f2 |
| The privileged | command | sudo tee /etc/file |
| The logging | make 2>&1 | tee build.log |
| The filter | command | tee full.log | grep 'ERROR' |
| The live | tail -f log | tee --line-buffered out |
| The process sub | command | tee >(gzip > out.gz) |
The tee vs the >
| The aspect | The tee | The > |
|---|---|---|
| The display | Yes | No |
| The pipeline | Continues | Ends |
| The multiple | Yes | No |
| The append | -a | >> |
| The sudo | Yes | No |
The Exit Status
| The status | The meaning |
|---|---|
| 0 | The success |
| 1 | The write error |
| 2 | The usage error |
Best Practices
โ Do This:
# Use the tee for the capture and the display
make 2>&1 | tee build.log # โ
# Use the -a for the append
command | tee -a /var/log/app.log # โ
# Use the sudo tee for the privileged write
echo 'config' | sudo tee /etc/app/config.conf # โ
# Use the --line-buffered for the live
tail -f log | tee --line-buffered out | grep 'ERROR' # โ
# Use the tee for the pipeline inspection
cat data | tee step1.txt | sort | tee step2.txt # โ
# Use the process substitution
command | tee >(gzip > out.gz) | wc -l # โ
โ Don’t Do This:
# Don't use the tee for the plain redirect
command | tee file.txt > /dev/null # the > file.txt is the simpler // โ
# Don't forget the -a for the log
command | tee /var/log/app.log # the truncates the log // โ
# Don't use the > for the sudo
sudo command > /etc/file # the permission denied // โ
# Don't use the block-buffered for the live
tail -f log | tee out | grep 'ERROR' # the delayed output // โ
(the --line-buffered is the fix)
# Don't write to the same file
command | tee file.txt > file.txt # the race // โ
# Don't use the tee when the redirect works
command | tee file.txt # the > file.txt is the simpler // โ
Common Pitfalls
| The pitfall | The why | The fix |
|---|---|---|
| The delayed output | The block-buffered | Use the --line-buffered |
| The log truncated | The no -a | Add the -a |
| The sudo fails | The > redirect | Use the sudo tee |
| The output doubled | The tee and the > | Remove the one |
| The write error | The full disk | Check the --output-error |
| The SIGINT kills the tee | The default | Use the -i |
| The process substitution fails | The bash only | Use the bash |
Real-World Examples
1. The Build Log
make 2>&1 | tee build.log
2. The Deploy Log
./deploy.sh 2>&1 | tee -a deploy.log
3. The Privileged Write
echo 'key=value' | sudo tee /etc/app/config.conf
4. The Filter
command | tee full.log | grep 'ERROR'
5. The Live Monitoring
tail -f app.log | tee --line-buffered archive.log | grep 'ERROR'
6. The Pipeline Inspection
cat data | tee step1.txt | sort | tee step2.txt | uniq -c
7. The Process Substitution
command | tee >(gzip > out.gz) | wc -l
8. The Logger
command | tee >(logger -t myapp) | head
9. The Multiple Files
command | tee /tmp/out.txt /var/log/app.log
10. The Complete
make 2>&1 | tee -a build.log | grep 'ERROR'
Visual
The tee Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE tee FLOW โ
โ โ
โ command | tee output.txt | grep 'pattern' โ
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โcommand โ โtee โ โgrep โ โ
โ โ โ โ โ โ โ โ
โ โ the โ โ the โ โ the โ โ
โ โ stdout โโโผโโโโบโ stdin โ โ stdin โ โ
โ โ โ โ โ โ โ โ
โ โ โ โ output โโโผโโโโบโ stdout โ โ
โ โ โ โ .txt โ โ โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ
โ The tee splits the stream: the file and the stdout. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The tee vs the Redirection
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE tee vs THE REDIRECTION โ
โ โ
โ THE `>` REDIRECTION: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ command > output.txt โ โ
โ โ โ the file has the output โ โ
โ โ โ the terminal has the nothing โ โ
โ โ โ the pipeline ends โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ THE `tee`: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ command | tee output.txt โ โ
โ โ โ the file has the output โ โ
โ โ โ the terminal has the output โ โ
โ โ โ the pipeline continues โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Privileged Write
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE PRIVILEGED WRITE โ
โ โ
โ โ THE `>` REDIRECTION: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ sudo echo 'config' > /etc/app.conf โ โ
โ โ โ the shell opens the /etc/app.conf as the USER โ โ
โ โ โ the permission denied โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โ
THE `tee`: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ echo 'config' | sudo tee /etc/app.conf โ โ
โ โ โ the tee runs as the ROOT โ โ
โ โ โ the tee opens the /etc/app.conf as the root โ โ
โ โ โ the success โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Multiple Destinations
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE MULTIPLE DESTINATIONS โ
โ โ
โ command | tee file1 file2 | grep 'pattern' โ
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โcommand โ โtee โ โgrep โ โ
โ โ โ โ โ โ โ โ
โ โ the โ โ the โ โ the โ โ
โ โ stdout โโโผโโโโบโ stdin โ โ stdin โ โ
โ โ โ โ โ โ โ โ
โ โ โ โ file1 โโโโผโโโโบโ stdout โ โ
โ โ โ โ file2 โ โ โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ
โ The tee writes to the multiple files and the stdout. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
tee | The stdin to the stdout and the files |
-a | The append |
-i | The ignore the SIGINT |
-p | The diagnose the write errors |
--line-buffered | The line-buffered |
--output-error | The write-error behavior |
| The pipeline | The continues |
| The sudo | The privileged write |
| The process substitution | The >() |
Key takeaways:
- The
teereads the standard input and writes to both the standard output and the files. Thecommand | tee output.txtsaves the output and continues the pipeline. Theteeis the T-splitter, and the pipe is the straight line. - The
-aappends to the file instead of the truncating. Thecommand | tee -a output.txtis the log rotation, and thecommand | tee output.txtis the fresh capture. - The
sudo teewrites to the root-owned file. Thesudo command > /etc/filefails, because the redirection runs in the user’s shell. Thecommand | sudo tee /etc/fileworks, because theteeruns with thesudo. - The
--line-bufferedmakes the output the line-buffered. The default is the block-buffered, and the live monitoring needs the line-buffered. Thetail -f log | tee --line-buffered outis the pattern. - The
teeis the pipeline inspection. Thecommand1 | tee step1.txt | command2 | tee step2.txt | command3saves the each stage, and the debugging is the easy. - The
teeis the logging. Themake 2>&1 | tee build.logcaptures the both the stdout and the stderr. The2>&1is the merge, and theteeis the capture. - The
teewrites to the multiple files. Thecommand | tee file1 file2writes to the both, and the process substitution extends the destinations. - The result is the output splitting. The pipe connects, and the
teebranches. The result is the capture without the losing, which is the foundation of the logging and the debugging.
Remember: The tee reads the standard input and writes to the standard output and the files. The -a appends, the sudo tee writes the privileged, and the --line-buffered makes the live. The result is the output splitting, which is the foundation of the shell pipelines.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!