Shell redirections explained

oyagci profile image Oguzhan Yagci ・3 min read

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?
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


$> 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. :)

Posted on by:

oyagci profile

Oguzhan Yagci


Student at 42, Paris.


Editor guide