Shell redirections explained
Tags: shell, bash, sh
Published: 2017-11-04 21:38:15

---
title: Shell redirections explained
published: true
description: Those little operators that are very useful
tags: shell,bash,sh
---

As a student I have to use my shell everyday to get my work done. A shell can be an extremely powerful tool in everyday life if you know how to use it.

Shell redirections are something you have to use in order to accomplish many tasks without pain. 

# How a program outputs its content on the terminal.

To output text on the terminal a program must write it's output into a file. The classical way to manipulate files on a UNIX-like operating system is by requesting to the OS a file descriptor (fd). An fd is an unsigned integer given by the OS that identifies a given file on the system.

**File descriptors are numbers that represent a way to access files.**

By default your program gets 3 file descriptors that are called `stdin`, `stdout` and `stderr`.

The first fd `stdin` is the file used by your program to read input. It's default value is `0`. If you start a program like `cat` without arguments it reads its input from `stdin`.

The second fd `stdout` is used to output content for the user (like "Hello World!"). It's default value is `1`.

The third fd open by default is `stderr`. This one works exactly like `stdout` except we mostly use it to output error messages. It's default value is `2`.


# Shell redirections operators

In a shell, there are a few operators to perform redirections. Those are `>`, `>>`, `<`, `<<`, `>&`, `<&`.

## `>`, `>>`, and `<`

Those 3 operators have one main thing in common: They interact with input/output files.

`>` and `>>` are used to redirect output from a program into a file.
```
$> cat my_file.txt > my_new_file.txt # The output from cat is redirect to a file caled my_new_file.txt
```
(If the file does not exist, it is created)

The difference between `>` and `>>` is that `>` truncates the file it is outputing to and `>>` appends to the output file.
```
$> echo Hello World! > greeting.txt # Creates a file with 'Hello World!' as the content

$> echo How are you? >> greeting.txt # Append 'How are you?' to greeting.txt
```
`<` allows you to use a file as input. So `stdin` becomes the file.

```
$> base64 < greeting.txt # base64 will use stdin as input which is redirected to greeting.txt by the shell
```
You can also combine multiple redirection operators:

```
$> cat < a.txt > b.txt # Reads from a.txt and outputs to b.txt
```

## And `<<`

That one is a bit like the three above, except that it does not interact with files. Instead it is used to get input from the user's keyboard line by line.

So when you do something like:
```
$> cat <<EOF
```
... and press enter, the shell will expect input.
So you can continue:
```
$> cat <<EOF
> Hello World!
> How are you?
> Do you know the answer to the ultimate question?
```
And when you want to stop the input you either press `Ctrl+D` or type the word which is on the right side of the `<<` operator (In this case `EOF`) and press enter (it must be on an empty line):

```
$> cat << EOF
> Hello World!
> How are you?
> Do you know the answer to the ultimate question?
> EOF
Hello World!
How are you?
Do you know the answer to the ultimate question?
```

Immediatly after the input has been stoppedt the shell runs the program with what you have typed as the content in `stdin`.

## `>&` and `<&`

Those two do not act on files but file descriptors.

Their left side can be either ignored or be a number (the target fd).
The left side MUST be attached to the operator.

If I want to redirect `stdout` to `stderr` I can do:
```
$> cat ft_strdup.c 1>&2
```
Or...

```
$> cat ft_strdup.c >&2
```

You can also use `>&` and `<&` to close a file descriptor (If you want to ignore error messages, for example)
```
$> find / -name 'lost_file' 2>&- # If you don't want to see messages like 'Permision denied'
```

The only difference between `>&` and `<&` is the default file descriptor used in case of a not given left fd.
`>&` is for `stdout` and `<&` is for `stdin`.

Also, if you put a space between the left side of the operator and the operator itself the shell will think that the left side is actually an argument to pass to the program and will use the default left side fd number.

## One last thing

Those operators can be used anywhere on the command line
```
$> < input_file cat

$> >output_file echo hello world

$> ls 2>&- -R /
```

But you should put the them either on the beginning of the command or the ending to avoid confusion.

I hope this article has been helpful to you. :)