# Redireccions d'entrada i sortida

A GNU/Linux, cada procés treballa amb tres **canals estàndard** de comunicació, coneguts com a *streams* estàndard:

| Canal | Nom | Descriptor | Per defecte |
|-------|-----|-----------|-------------|
| Entrada estàndard | `stdin` | `0` | Teclat |
| Sortida estàndard | `stdout` | `1` | Pantalla (terminal) |
| Sortida d'errors | `stderr` | `2` | Pantalla (terminal) |

La **redirecció** permet canviar l'origen o la destinació d'aquests canals: llegir des d'un fitxer en comptes del teclat, escriure la sortida en un fitxer en comptes de la pantalla, o enviar la sortida d'un programa com a entrada d'un altre.

## 1. Descriptors de fitxer

El nucli Linux identifica cada canal obert amb un **descriptor de fitxer** (un nombre enter):

![Descriptors](https://proferamon.com/tic/imatges/redireccions/redireccions01.png)

Quan es redirecciona, es canvia a quin fitxer o dispositiu apunta cada descriptor.

## 2. Redirecció de la sortida estàndard (`stdout`)

### `>` — Redirigir a un fitxer (sobreescriu)

Envia la sortida d'una ordre a un fitxer. Si el fitxer ja existeix, el **sobreescriu**.

```bash
ls -l > llistat.txt
echo "Hola món" > salutació.txt
date > data_actual.txt
```

> Si el fitxer existeix, el seu contingut anterior es **perd**.

### `>>` — Afegir a un fitxer (no sobreescriu)

Afegeix la sortida al **final** del fitxer. Si el fitxer no existeix, el crea.

```bash
echo "Primera línia" > notes.txt
echo "Segona línia" >> notes.txt
echo "Tercera línia" >> notes.txt
```

Resultat de `notes.txt`:

```ini
Primera línia
Segona línia
Tercera línia
```

## 3. Redirecció de la sortida d'errors (`stderr`)

### `2>` — Redirigir errors a un fitxer

El descriptor `2` correspon a `stderr`. S'utilitza per capturar els **missatges d'error** separadament.

```bash
ls /directori_inexistent 2> errors.txt
find / -name "fitxer.txt" 2> /dev/null
```

### `2>>` — Afegir errors a un fitxer

```bash
./script.sh 2>> registre_errors.log
```

## 4. Redirecció de `stdout` i `stderr` simultàniament

### `> fitxer 2>&1` — Tots dos canals al mateix fitxer

`2>&1` significa "redirigeix el descriptor 2 cap on apunta el descriptor 1".

```bash
ls -l /etc > sortida.txt 2>&1
./script.sh > tot.log 2>&1
```

> ⚠️ **L'ordre importa**: primer s'ha de redirigir `stdout` i després `2>&1`. A l'inrevés no funciona correctament.

### `&>` — Sintaxi abreujada de Bash (Bash 4+)

```bash
ls -l /etc &> sortida_i_errors.txt
./script.sh &>> registre.log    # afegint
```

### Separar `stdout` i `stderr` en fitxers diferents

```bash
./script.sh > sortida.txt 2> errors.txt
```

## 5. Redirecció de l'entrada estàndard (`stdin`)

### `<` — Llegir des d'un fitxer

Substitueix el teclat per un fitxer com a font d'entrada.

```bash
sort < llista_desordenada.txt
wc -l < document.txt
mail -s "Assumpte" usuari@exemple.com < missatge.txt
```

### `<<` — *Here Document* (document incrustrat)

Permet introduir múltiples línies d'entrada directament a l'intèrpret, fins a trobar una paraula delimitadora.

```bash
cat << FI
Això és un here document.
Pot tenir múltiples línies.
S'acaba quan apareix la paraula delimitadora.
FI
```

Útil en scripts:

```bash
mysql -u root -p base_de_dades << SQL
SELECT * FROM usuaris;
DROP TABLE temporal;
SQL
```

### `<<<` — *Here String* (cadena incrustrada)

Passa una cadena de text directament com a `stdin`.

```bash
grep "hola" <<< "hola món"
bc <<< "5 * 8 + 3"
```

## 6. La canonada (`|`) — Pipe

L'operador `|` connecta la **sortida estàndard** d'una ordre amb l'**entrada estàndard** de la següent. Permet encadenar ordres per crear pipelines potents.

```bash
ordre1 | ordre2 | ordre3
```

```bash
ls -l | grep ".txt"
cat fitxer.txt | sort | uniq
ps aux | grep apache | wc -l
cat /etc/passwd | cut -d: -f1 | sort
```

### Pipeline amb `stderr`

Per defecte, la canonada només transmet `stdout`. Per incloure `stderr`:

```bash
./script.sh 2>&1 | grep "error"
./script.sh |& grep "error"      # sintaxi abreujada Bash
```

## 7. El dispositiu `/dev/null`

`/dev/null` és un dispositiu especial que **descarta tot el que hi escrius** i retorna EOF quan el llegeixes. S'utilitza per silenciar sortides no desitjades.

```bash
# Silenciar sortida estàndard
ls /etc > /dev/null

# Silenciar errors
find / -name "passwd" 2> /dev/null

# Silenciar tot
./script.sh > /dev/null 2>&1

# Buidar un fitxer sense esborrar-lo
> fitxer.txt
cat /dev/null > fitxer.txt
```

## 8. `tee` — Escriure i mostrar alhora

L'ordre `tee` llegeix de `stdin` i escriu simultàniament a `stdout` **i** a un fitxer. És com una "T" en una canonada.

```bash
ls -l | tee llistat.txt
./script.sh | tee -a registre.log    # -a per afegir
```

![Escriure i mostrar alhora](https://proferamon.com/tic/imatges/redireccions/redireccions02.png)

## 9. Resum dels operadors de redirecció

| Operador | Funció |
|----------|--------|
| `>` | Redirigir `stdout` a fitxer (sobreescriu) |
| `>>` | Afegir `stdout` a fitxer |
| `<` | Llegir `stdin` des d'un fitxer |
| `2>` | Redirigir `stderr` a fitxer (sobreescriu) |
| `2>>` | Afegir `stderr` a fitxer |
| `2>&1` | Redirigir `stderr` cap on va `stdout` |
| `&>` | Redirigir `stdout` i `stderr` a fitxer |
| `&>>` | Afegir `stdout` i `stderr` a fitxer |
| `|` | Canonada: `stdout` d'una ordre → `stdin` de la següent |
| `|&` | Canonada incloent `stderr` |
| `<<DELIM` | Here document |
| `<<<` | Here string |


## 10. Exemples pràctics combinats

### Guardar la sortida d'una ordre i veure-la a la vegada
```bash
df -h | tee espai_disc.txt
```

### Comptar línies que contenen errors en un log
```bash
grep "ERROR" /var/log/syslog | wc -l
```

### Ordenar i eliminar duplicats d'una llista
```bash
cat llista.txt | sort | uniq > llista_neta.txt
```

### Executar script guardant tota la sortida (stdout + stderr)
```bash
./deploy.sh > deploy.log 2>&1
```

### Cerca silenciosa (sense mostrar errors de permisos)
```bash
find /home -name "*.conf" 2> /dev/null
```

### Enviar el contingut d'un fitxer per correu
```bash
mail -s "Informe diari" admin@empresa.cat < informe.txt
```

### Generar un fitxer de configuració amb here document
```bash
cat > /etc/app/config.conf << EOF
servidor=192.168.1.10
port=8080
debug=false
EOF
```

### Pipeline complex: els 5 processos que més CPU consumeixen
```bash
ps aux | sort -k3 -rn | head -6 | tail -5
```

## 11. Errors comuns

### Sobreescriure un fitxer sense voler
```bash
# Perill: sobreescriu fitxer.txt!
sort fitxer.txt > fitxer.txt    # el fitxer queda buit
# Correcte: usar fitxer temporal
sort fitxer.txt > fitxer_ordenat.txt && mv fitxer_ordenat.txt fitxer.txt
```

### Ordre incorrecte en `2>&1`
```bash
# Incorrecte: stderr no va al fitxer
./script.sh 2>&1 > sortida.txt

# Correcte: primer redirigir stdout, després 2>&1
./script.sh > sortida.txt 2>&1
```

### Confondre `>` amb `>>`
```bash
# Cada cop que s'executa, esborra el contingut anterior
echo "entrada" > registre.log

# Acumula les entrades
echo "entrada" >> registre.log
```

## 12. Protecció contra sobreescriptura (`noclobber`)

Bash permet activar l'opció `noclobber` per evitar sobreescriure fitxers existents accidentalment:

```bash
set -o noclobber        # activar
set +o noclobber        # desactivar

# Amb noclobber actiu, per forçar la sobreescriptura:
echo "text" >| fitxer.txt
```

#### Versions d'aquest document

+ HTML - [redireccions.html](https://proferamon.com/tic/redireccions.html)
+ PDF - [redireccions.pdf](https://proferamon.com/tic/docs/redireccions.pdf)
+ ODT - [redireccions.odt](https://proferamon.com/tic/odt/redireccions.odt)
+ MD - [redireccions.md](https://proferamon.com/tic/md/redireccions.md)

[Domini Públic (CC0)](https://creativecommons.org/publicdomain/zero/1.0/deed.ca)

