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