# 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. |
