Linux CLI 11๐ง Input/Output and redirection
Every command in Linux works with three standard streams โ and you can redirect them to files, other commands, or the void. This is one of the most powerful concepts in the shell.
The Three Standard Streams
Every process on Linux has three standard I/O streams:
| Stream | Name | Default Source/Destination | File Descriptor |
|---|---|---|---|
| stdin | Standard Input | Keyboard | 0 |
| stdout | Standard Output | Terminal | 1 |
| stderr | Standard Error | Terminal | 2 |
Visual:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Program โ
โ โ
โ stdin (0) โโโ โโโโโโโโโโโ โ
โ Keyboard โ Process โ โ
โ โโโโโโฌโโโโโ โ
โ โ โ
โ stdout (1) โโโโค โ
โ stderr (2) โโโโ โ
โ โ โ
โ โผ โ
โ Terminal โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Key points:
- stdin โ where the program reads input (usually the keyboard)
- stdout โ where the program writes regular output (usually the terminal)
- stderr โ where the program writes errors (usually the terminal)
- Each stream has a file descriptor (a number the kernel uses)
stdin=0,stdout=1,stderr=2
Basic Redirection: stdout
echo "I am Kronos" > output.txt
This redirects the stdout of echo to the file output.txt โ overwriting anything that was there.
What happens:
- Without
>: output goes to the terminal - With
>: output goes to a file (terminal shows nothing) - The file is created if it doesn’t exist
- The file is overwritten if it does exist
Examples:
$ echo "Hello" > file.txt
$ cat file.txt
Hello
$ echo "World" > file.txt # Overwrites!
$ cat file.txt
World
Redirection Operators
Linux has several operators to redirect the standard streams:
| Operator | Description | Example |
|---|---|---|
> | Redirect stdout to a file (overwrite) | echo "Hi" > file.txt |
>> | Redirect stdout to a file (append) | echo "Hi" >> file.txt |
< | Redirect stdin from a file | sort < input.txt |
2> | Redirect stderr to a file | ls bad 2> error.txt |
2>> | Redirect stderr (append) | ls bad 2>> error.txt |
&> | Redirect both stdout and stderr to a file | cmd &> all.txt |
&>> | Redirect both (append) | cmd &>> all.txt |
2>&1 | Redirect stderr to where stdout is going | cmd > out.txt 2>&1 |
1> | Explicitly redirect stdout (same as >) | cmd 1> out.txt |
The >> Operator โ Append
echo "My son is Zeus" >> output.txt
cat output.txt
Redirects stdout to a file but appends instead of overwriting.
Comparison:
# > overwrites
$ echo "Line 1" > file.txt
$ echo "Line 2" > file.txt
$ cat file.txt
Line 2
# >> appends
$ echo "Line 1" > file.txt
$ echo "Line 2" >> file.txt
$ cat file.txt
Line 1
Line 2
Visual:
> : [old content] โโโ [new content] (old erased)
>> : [old content] โโโ [old content + new] (old kept)
When to use >>:
- Adding to log files
- Building up a file incrementally
- Preserving previous data
The < Operator โ Redirect stdin
sort < output.txt
Redirects stdin from a file โ the command reads from the file instead of the keyboard.
Example:
# Without redirect โ sort waits for keyboard input
$ sort
banana
apple
cherry
# Press Ctrl+D to finish
apple
banana
cherry
# With redirect โ reads from file
$ sort < fruits.txt
apple
banana
cherry
Common use cases:
sort < data.txt # Sort a file
wc -l < data.txt # Count lines
grep "error" < log.txt # Search a file
Redirecting stderr (2>)
ls out.txt
ls out.txt 2> error.txt
cat error.txt
Why separate stdout and stderr?
- Regular output and error messages are different things
- Sometimes you want to save only errors
- Or hide errors while showing output
Example:
# ls out.txt โ file doesn't exist
$ ls out.txt
ls: cannot access 'out.txt': No such file or directory
# Redirect the error to a file
$ ls out.txt 2> error.txt
# (no output on terminal)
$ cat error.txt
ls: cannot access 'out.txt': No such file or directory
File descriptors in the command:
| Syntax | Meaning |
|---|---|
2> | Redirect stderr (fd 2) to a file |
1> | Redirect stdout (fd 1) to a file |
0< | Redirect stdin (fd 0) from a file |
Redirecting stdout and stderr
To Different Files
ls out.txt output.txt > lslog.txt 2> error.txt
- stdout โ
lslog.txt - stderr โ
error.txt
Example:
$ ls existing.txt missing.txt > success.txt 2> errors.txt
$ cat success.txt
existing.txt
$ cat errors.txt
ls: cannot access 'missing.txt': No such file or directory
To the Same File
ls out.txt &> log.txt
- Both stdout and stderr โ
log.txt
Equivalent forms:
# Modern (bash 4+)
cmd &> file.txt
# Traditional (POSIX-compatible)
cmd > file.txt 2>&1
Note: The order matters! 2>&1 must come after >.
cmd > file.txt 2>&1 # โ
Both go to file.txt
cmd 2>&1 > file.txt # โ stderr goes to terminal, stdout to file
Why? 2>&1 means “make fd 2 point where fd 1 currently points.” If > hasn’t redirected fd 1 yet, fd 2 goes to the terminal.
The /dev/null โ The Void
ls d1 1> /dev/null
ls d1 2> /dev/null
/dev/null is a special file that accepts input and does nothing with it โ the black hole of Linux.
| Command | Effect |
|---|---|
cmd > /dev/null | Discard stdout |
cmd 2> /dev/null | Discard stderr |
cmd &> /dev/null | Discard everything |
Examples:
# Hide stdout, show stderr
$ ls existing.txt missing.txt > /dev/null
ls: cannot access 'missing.txt': No such file or directory
# Hide stderr, show stdout
$ ls existing.txt missing.txt 2> /dev/null
existing.txt
# Hide everything
$ ls existing.txt missing.txt &> /dev/null
# (no output)
# Check if a command succeeds silently
$ if ls /nonexistent &> /dev/null; then
echo "exists"
else
echo "not found"
fi
Why it’s useful:
- Testing โ run commands without noise
- Cron jobs โ prevent email spam from output
- Scripts โ hide messages you don’t need
- Silencing errors โ hide expected errors
Complete Example Session
# ============================================
# PART 1: REDIRECT STDOUT
# ============================================
$ echo "I am Kronos" > output.txt
$ cat output.txt
I am Kronos
# Overwrite
$ echo "I am Zeus" > output.txt
$ cat output.txt
I am Zeus
# ============================================
# PART 2: APPEND WITH >>
# ============================================
$ echo "My son is Zeus" >> output.txt
$ cat output.txt
I am Zeus
My son is Zeus
$ echo "My wife is Hera" >> output.txt
$ cat output.txt
I am Zeus
My son is Zeus
My wife is Hera
# ============================================
# PART 3: REDIRECT STDIN WITH <
# ============================================
$ cat > fruits.txt
banana
apple
cherry
# Press Ctrl+D
$ sort < fruits.txt
apple
banana
cherry
# ============================================
# PART 4: REDIRECT STDERR WITH 2>
# ============================================
$ ls out.txt
ls: cannot access 'out.txt': No such file or directory
$ ls out.txt 2> error.txt
$ cat error.txt
ls: cannot access 'out.txt': No such file or directory
# ============================================
# PART 5: REDIRECT BOTH STREAMS
# ============================================
# To different files
$ ls output.txt missing.txt > success.txt 2> errors.txt
$ cat success.txt
output.txt
$ cat errors.txt
ls: cannot access 'missing.txt': No such file or directory
# To the same file
$ ls output.txt missing.txt &> combined.txt
$ cat combined.txt
ls: cannot access 'missing.txt': No such file or directory
output.txt
# Traditional syntax
$ ls output.txt missing.txt > combined.txt 2>&1
# ============================================
# PART 6: /dev/null
# ============================================
# Hide stdout
$ ls output.txt missing.txt > /dev/null
ls: cannot access 'missing.txt': No such file or directory
# Hide stderr
$ ls output.txt missing.txt 2> /dev/null
output.txt
# Hide everything
$ ls output.txt missing.txt &> /dev/null
# (no output)
# ============================================
# PART 7: PRACTICAL EXAMPLES
# ============================================
# Log output of a script
$ ./backup.sh > backup.log 2>&1
# Save errors separately
$ ./backup.sh > backup.log 2> backup-errors.log
# Discard output but keep errors
$ ./quiet.sh > /dev/null
# Silent check
$ if ping -c 1 google.com &> /dev/null; then
echo "Online"
else
echo "Offline"
fi
# Redirect output of multiple commands
$ { echo "Line 1"; echo "Line 2"; } > multi.txt
$ cat multi.txt
Line 1
Line 2
# Redirect with tee (view AND save)
$ ls | tee ls-output.txt
# Shows output AND saves to file
Quick Reference
Redirection Operators
| Operator | Description |
|---|---|
> | Redirect stdout (overwrite) |
>> | Redirect stdout (append) |
< | Redirect stdin from file |
2> | Redirect stderr (overwrite) |
2>> | Redirect stderr (append) |
&> | Redirect both stdout + stderr (overwrite) |
&>> | Redirect both (append) |
2>&1 | Point stderr to where stdout goes |
> /dev/null | Discard stdout |
2> /dev/null | Discard stderr |
&> /dev/null | Discard everything |
File Descriptors
| FD | Name | Default |
|---|---|---|
0 | stdin | Keyboard |
1 | stdout | Terminal |
2 | stderr | Terminal |
/dev/null
| Aspect | Description |
|---|---|
| Purpose | Discards everything written to it |
| Use case | Silencing output/errors |
| Type | Special character device |
| Also | Reading from it returns EOF immediately |
Best Practices
โ Do This:
# Use >> for logs
echo "$(date): backup started" >> backup.log
# Separate errors from output
./script.sh > output.log 2> errors.log
# Combine when debugging
./script.sh > all.log 2>&1
# Order matters with 2>&1
cmd > file 2>&1 # โ
Both to file
cmd 2>&1 > file # โ Wrong order
# Use /dev/null to silence
cron-job &> /dev/null
# Test with tee to see AND save
long-command | tee output.txt
# Check exit codes even with redirection
if cmd > /dev/null 2>&1; then
echo "success"
fi
โ Don’t Do This:
# Don't overwrite important files with >
cat important.log > important.log # โ Erases file!
cat important.log >> important.log # โ
Appends
# Don't redirect stderr without redirecting stdout
cmd 2> errors.txt # โ
stderr saved, stdout shown
cmd > output.txt # โ
stdout saved, stderr shown
cmd 2> errors.txt > output.txt # โ
Both saved separately
# Don't use > when you want to keep old content
echo "new log entry" > log.txt # โ Overwrites whole log
echo "new log entry" >> log.txt # โ
Appends to log
# Don't forget the order with 2>&1
cmd 2>&1 > file.txt # โ stderr goes to terminal!
cmd > file.txt 2>&1 # โ
Correct
# Don't redirect to /dev/null when debugging
./script.sh &> /dev/null # โ You see nothing!
./script.sh # โ
Debug normally
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
> overwrites | Loses old data | Use >> for appending |
2>&1 order | stderr not redirected | Put 2>&1 after > |
| Redirection on nonexistent dir | Error | Create dir first |
/dev/null on important data | Data lost | Use tee to save |
| Confusing stderr and stdout | Wrong file gets error | Use 2> for stderr |
Bash-specific &> in scripts | Not portable | Use > file 2>&1 |
Real-World Examples
1. Logging Script Output
#!/bin/bash
# Run backup, save both stdout and stderr to log
./backup.sh >> /var/log/backup.log 2>&1
# Save output and errors separately
./backup.sh > backup-success.log 2> backup-error.log
2. Silent Cron Jobs
# In crontab โ run every hour, no email
0 * * * * /usr/local/bin/cleanup.sh &> /dev/null
3. Test If Command Exists
if command -v git &> /dev/null; then
echo "Git is installed"
else
echo "Please install Git"
fi
4. Suppress Expected Errors
# Find files, ignore permission errors
find / -name "*.conf" 2> /dev/null
# List directories, ignore "not found" errors
ls -d */ 2> /dev/null
5. Build Incremental Log
#!/bin/bash
LOG="build.log"
echo "===== Build started $(date) =====" >> $LOG
make >> $LOG 2>&1
echo "===== Build finished $(date) =====" >> $LOG
6. View and Save with tee
# See output AND save to file
ls -la | tee directory-listing.txt
# Append instead of overwrite
ls -la | tee -a directory-listing.txt
# Save and see, but suppress errors
command 2> /dev/null | tee output.txt
7. Redirect Only Errors
# Run script, show output, save errors
./script.sh 2> errors.log
# Run script, discard output, see errors
./script.sh > /dev/null
Visual: Redirection Flow
BEFORE (no redirection):
Command โโstdoutโโโ Terminal
โโstderrโโโ Terminal
AFTER (echo "Hi" > file.txt):
Command โโstdoutโโโ file.txt
โโstderrโโโ Terminal
AFTER (cmd &> file.txt):
Command โโstdoutโโโ file.txt
โโstderrโโโ file.txt
AFTER (cmd 2> /dev/null):
Command โโstdoutโโโ Terminal
โโstderrโโโ /dev/null (discarded)
Summary
| Concept | Description |
|---|---|
| stdin (0) | Input, usually keyboard |
| stdout (1) | Output, usually terminal |
| stderr (2) | Errors, usually terminal |
> | Redirect stdout, overwrite |
>> | Redirect stdout, append |
< | Redirect stdin from file |
2> | Redirect stderr |
&> | Redirect both |
2>&1 | Point stderr to stdout |
/dev/null | Discards everything |
Key takeaways:
- Every command has three streams: stdin (0), stdout (1), stderr (2)
>overwrites,>>appends2>redirects errors separately from output&>or> file 2>&1redirects both streams/dev/nullis the void โ use it to silence output or errors- Order matters โ
2>&1must come after>to work correctly - Use
teewhen you want to see AND save output
Remember: Redirection is what makes the shell composable. It lets you chain commands, save output, discard noise, and control exactly where every byte goes. Master >, >>, 2>, and /dev/null, and you’ll write far more powerful scripts. The three streams are the plumbing of the command line โ once you understand them, everything clicks!
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!