Files
linux.softwareshinobi.com/landing/docs/Bash-Scripts/023-bash-redirection.md

218 lines
5.5 KiB
Markdown
Raw Normal View History

2025-06-19 10:03:08 -04:00
# Redirection
Master Bash redirection and pipes. These essential Linux features are critical for efficient system administration. Every command handles input, output, and errors through **File Descriptors (FDs)**:
* **STDIN** (0): Standard Input receives data.
* **STDOUT** (1): Standard Output sends regular data.
* **STDERR** (2): Standard Error sends error messages.
---
### Pipes vs. Redirection
Both manage data streams, but with a key difference:
* **Redirection** routes a command's input/output to or from a **file**.
* **Pipes** (`|`) connect the **output of one command directly to the input of another command**.
---
### STDIN (Standard Input)
Commands often expect input. By default, this is your keyboard, but you can redirect it from other sources.
**Redirecting from a file (`<`)**:
Use `<` to feed a file's content as input to a command. Create `input.txt`:
```bash
touch input.txt
```
Open `input.txt` and add:
```
Line 1
Line 2
```
Save `input.txt`.
Then run:
```bash
cat < input.txt
```
This prints `input.txt` content, similar to `cat input.txt`.
**Here-Documents (`<< DELIMITER`)**:
For multi-line input directly in your script or terminal, use a here-document with a custom delimiter (e.g., `EOF`).
```bash
cat << EOF
Hello World!
How are you?
EOF
```
This will print:
```
Hello World!
How are you?
```
Similarly, with `wc -l` to count lines:
```bash
wc -l << EOF
Hello World!
How are you?
EOF
```
Output:
```
2
```
---
### STDOUT (Standard Output)
Regular command output typically goes to your terminal. Redirect it to a file.
**Overwrite (`>`)**:
Use `>` to send output to a file. If the file exists, its content is overwritten. Create `file.txt` (or ensure it's empty):
```bash
echo "Hello World!" > file.txt
cat file.txt # Output: Hello World!
```
Running again overwrites:
```bash
echo "How are you?" > file.txt
cat file.txt # Output: How are you? (Previous content is gone)
```
**Append (`>>`)**:
Use `>>` to add output to the end of a file without overwriting existing content.
```bash
echo "Hello World!" > file.txt # Start fresh
echo "How are you?" >> file.txt
cat file.txt
```
Output:
```
Hello World!
How are you?
```
You can also explicitly specify the STDOUT file descriptor (1): `echo "Hello" 1> file.txt`.
---
### STDERR (Standard Error)
Error messages, distinct from standard output, are sent to **STDERR**. Redirect them using file descriptor 2.
**Redirecting Errors (`2>`)**:
Use `2>` to redirect error messages. For example, `ls --invalid-flag` generates an error.
```bash
ls --invalid-flag 2> error.txt
cat error.txt # Contains the error message
```
Use `2>>` to append error messages to a file.
**Discarding Errors (`2> /dev/null`)**:
Send error output to `/dev/null` to completely suppress it. `/dev/null` is a special 'black hole' device that discards all data written to it.
```bash
ls --invalid-flag 2> /dev/null # Error message is hidden
```
**Redirecting Both STDOUT and STDERR**:
You can manage both streams simultaneously.
To separate regular output and errors into different files:
```bash
# Assuming 'install_package.sh' generates both output and errors
./install_package.sh > output.txt 2> error.txt
```
To send both to the same file (concise syntax):
```bash
./install_package.sh > combined_output.txt 2>&1
```
The `2>&1` redirects file descriptor 2 (STDERR) to the same location as file descriptor 1 (STDOUT), which is `combined_output.txt`. Alternatively, an even shorter Bash 4+ syntax: `&> combined_output.txt`.
---
### Piping (`|`)
Pipes connect the standard output of one command directly to the standard input of another, creating powerful command chains.
**Basic Example:** Find `.txt` files in a directory listing.
```bash
ls | grep ".txt"
```
This sends `ls`'s output to `grep` for filtering.
**Chaining Commands:** Analyze file ownership in a directory.
```bash
ls -l /projects/bash_scripts | tail -n +2 | sed 's/\s\s*/ /g' | cut -d ' ' -f 3 | sort | uniq -c
```
This sequence lists files, removes the header, cleans spacing, extracts owner names, sorts them, and counts unique occurrences.
---
### Here-Documents (`<< DELIMITER`)
Here-documents (`<<`) provide multi-line input directly within your script or terminal, ideal for commands that read from STDIN without needing a separate temporary file.
Specify a custom delimiter (e.g., `EOF`):
```bash
cat << END_MESSAGE
This text will be passed as input to cat.
It spans multiple lines.
END_MESSAGE
```
Output:
```
This text will be passed as input to cat.
It spans multiple lines.
```
You can also pipe the output of a here-document to another command:
```bash
wc -l << MESSAGE_LINES
Line one.
Line two.
Line three.
MESSAGE_LINES
```
Output: `3` (counts the lines). Variables are expanded within here-documents.
---
### Here-Strings (`<<<`)
For piping a single string into a command's STDIN, use a here-string (`<<<`). This is cleaner than a here-document for single lines.
```bash
wc -w <<<"This is a sample string for word count."
```
Output: `7` (counts words).
Variables are also supported in here-strings.
---
### Summary of Redirection and Piping Operators
| **Operator** | **Description** |
| :--- | :--- |
| `>` | Redirect STDOUT to a file, overwriting existing content. |
| `>>` | Redirect STDOUT to a file, appending to existing content. |
| `<` | Redirect STDIN from a file. |
| `2>` | Redirect STDERR to a file, overwriting existing content. |
| `|` | Pipe STDOUT of one command to STDIN of another. |
| `<<` | Here-document: Provide multi-line STDIN from the script. |
| `<<<` | Here-string: Provide single-line STDIN from the command line. |