Redirecting Input & Output Streams
19 min read·Jan 1, 2025
By default, all the commands executed in a shell read their input from and write their output to the terminal.
However, it is sometimes useful to be able to change this behavior so that commands can read from and write to files instead of the terminal.
This can be achieved using a feature called input/output redirections.
A redirection is the action of capturing the output from a file, a program, or a script and sending it as input to another file, program, or script.
These redirections are mostly used for reading the content of a file, saving the output of a command into a file, or even chaining multiple commands together to create a data processing pipeline.
Standard streams
A stream is a communication channel that transfers data between a program and its environment, like for example the shell and its terminal.
In Unix-like operating systems, there are three types of streams called standard streams:
- The standard input, often abbreviated stdin, that programs can read data from.
- The standard output, often abbreviated stdout, that programs can write data to when a successful operation was performed.
- The standard error, often abbreviated stderr, that programs can write data to when something goes wrong during their execution.
These streams are by default attached to the terminal the shell runs in so that programs can use them, like for example the echo command that writes back its supplied arguments on the standard output.
File descriptors
A file descriptor is a unique resource identifier (i.e., an integer) assigned to a data stream by the operating system.
Whenever launching a new terminal window, the operating system automatically assigns the same file descriptor to each standard stream, which are:
0forstdin.1forstdout.2forstderr.
Displaying the content of files
To display the content of one or more files to the standard output, you can use the cat command — which stands for concatenate and print — as follows:
$ cat file ...
Where file ... is a list of paths to the files you want to display.
Example
This command will write the content of the hello.txt file to the standard output:
$ cat hello.txt
Hello world
Hallo Welt
Bonjour monde
Hola mundo
Redirecting output streams
Redirecting an output stream essentially consists in redirecting the standard output and/or the standard error of a command, so that it writes into a file instead of the terminal window, using the following syntax:
$ command fd> file
Where:
fdis a file descriptor.>is the output redirection operator.fileis the path to the file the executed command will write to.
Note: If the destination file doesn't exist, the redirection operator will automatically create it for you.
Redirecting stdout into a file
To redirect the standard output into a file, you can use the following syntax:
$ command 1> file
Note: In case of the standard output,
1>is equivalent to>.
Example
This command will write the string "Hello World" to the standard output:
$ echo "Hello World"
Hello World
This command will write the same string into a file named hello.txt by redirecting the file descriptor 1 (i.e. stdout) into that file instead of the terminal window:
$ echo "Hello World" > hello.txt
This command will display the content of the newly created hello.txt file:
$ cat hello.txt
Hello World
Redirecting stderr into a file
To redirect the standard error into a file, you can use the following syntax:
$ command 2> file
Note that you can combine multiple redirections by specifying them one after the other.
$ command > file 2> file
Example
This command will write an error to the standard error (i.e. stderr):
$ ls xxx
ls: xxx: No such file or directory
This command will write the same error into a file named error.txt by redirecting the file descriptor 2 (i.e., stderr) into that file instead of the terminal window:
$ ls xxx 2> error.txt
This command will display the content of the newly created error.txt file:
$ cat error.txt
ls: xxx: No such file or directory
Overwriting and appending to a file
By default, the output redirection operator > will completely overwrite the content of the specified destination file.
To prevent this from happening, you can use a double right chevron >> that will tell the shell to append the output of the executed command to the file's content instead of replacing it:
$ command fd>> file
Example
This command will write the string "Good morning" to the hello.txt file:
$ echo "Good morning" > hello.txt
$ cat hello.txt
Good morning
This command will completely overwrite the content of the hello.txt file with the string "Guten Tag":
$ echo "Guten Tag" > hello.txt
$ cat hello.txt
Guten Tag
This command will append the string "Buenos dias" at the end of the hello.txt file:
$ echo "Buenos dias" >> hello.txt
$ cat hello.txt
Guten Tag
Buenos dias
Silencing a file descriptor
It will sometimes happen that a stream creates too much noise in the terminal or in a file by generating an excessive amount of data.
To silence this stream, you can redirect its output in a special file called /dev/null, that acts as a kind of black hole that simply discards all the data it receives:
$ command fd> /dev/null
Example
This command will silence the standard error, thus preventing it from outputting any errors the ls command might encounter:
$ ls xxx 2> /dev/null
Redirecting streams into streams
When redirecting an output stream into a file, the shell will first try to create the file if it doesn't exist, and then open this file for writing.
When doing so, the operating system will attribute this file to a file descriptor and send it back to the shell, so it knows where to redirect the stream of data sent through the standard output or the standard error.
Consequently, redirecting the output of a command into a file essentially consists in redirecting a stream into a stream.
That being said, it is possible to manually redirect a stream into a stream using the following syntax:
$ command M>&N
Where:
Mis a file descriptor.>&is the output stream redirection operator.Nis a file descriptor.
Note: You can use the following syntax to redirect both stdout and stderr at once into the same file:
$ command &> file
Example
This command will redirect the standard output into a file named logs.txt and redirect the standard error into the standard output:
$ ls . xxx >> logs.txt 2>&1
Which will result in both streams being redirected to the same file:
$ cat logs.txt
ls: xxx: No such file or directory
/home/razvan:
Documents
Downloads
Library
Pictures
Projects
Public
Feeding data to a program through stdin
By default, many commands like cat will read data from the standard input when not supplied with a filepath argument.
These commands will read data until they encounter an end-of-file (EOF), which is a special sequence that indicates the end of a file or a data set.
This behavior can be illustrated by executing the cat command without arguments, which will result in the program awaiting for the user to type and send data through the standard input:
$ cat
▮
When typing a string and pressing ENTER:
$ cat
Hello World▮
The cat command will read this data from the standard input and write it back to the standard output, which is normal since all three standard streams are, by default, attached to the terminal:
$ cat
Hello World
Hello World
▮
Finally, to send an end-of-file sequence indicating that the data set is finished, you can use the CTRL + D key combination, which will cause the process to terminate and the command prompt to reappear, allowing you to type other commands:
$ cat
Hello World
Hello World
$
Redirecting input streams
Redirecting an input stream consists in redirecting the standard input of a command, so that it reads from a file instead of the terminal, using the following syntax:
$ command < file
Where:
<is the input redirection operator.fileis the path to the file the command should read from.
Example
Let's consider this file named lorem.txt:
$ cat lorem.txt
Lorem ipsum dolor sit amet.
Etiam eu pulvinar magna.
Phasellus ultricies neque libero.
This command will read its input from the lorem.txt file instead of the standard input and write it back to the terminal on the standard output:
$ cat < lorem.txt
Lorem ipsum dolor sit amet.
Etiam eu pulvinar magna.
Phasellus ultricies neque libero.
Input redirection vs filepath argument
Although the produced output is identical using either of these methods, there is a slight difference between passing a file as an argument and through an input redirection.
When passing a file as an argument, you are putting the specified command in charge of opening the file, reading its content, and writing it to the terminal.
On the other hand, when passing the content of the file through an input redirection, you are putting the shell in charge of opening the file and sending its content to the specified command to be then written back to the terminal.
Chaining commands with pipes
A pipe | is a special redirection operator that enables to feed the standard output of a command into the standard input of another command to form a processing pipeline using the following syntax:
$ command | command [| command]
Note: Pipes are mostly used in combination with filter commands, such as
sort,uniq,head, ortailto process data in various ways.
Sorting the output of a command
To sort the output of a command in alphabetical order, you can use the sort command as follows:
$ command | sort
Example
Let's consider this file named cities.txt:
$ cat cities.txt
Athens
Bucharest
Kiev
Madrid
Paris
This cat command will write the content of the cities.txt file to the standard output, which will then be piped into (or forwarded to) the standard input of the sort command, and finally printed in reverse alphabetical order using the -r flag (short for reverse):
$ cat cities.txt | sort -r
Paris
Madrid
Kiev
Bucharest
Athens
Deduplicating the output of a command
To filter out repeated adjacent lines, you can use the uniq command as follows:
$ command | uniq
Example
Let's consider this file named students.txt:
$ cat students.txt
Rose
Anna
Jack
Anna
Rose
This cat command will write the content of the students.txt file to the standard output, which will then be piped into the standard input of the sort command, whose output will be piped into the standard input of the uniq command, and finally printed without duplicated lines:
$ cat students.txt | sort | uniq
Anna
Jack
Rose
Displaying the first and last lines of a file
To respectively display the first and last lines of a file, you can use the head and tail command as follows:
$ command | head
$ command | tail
Example
Let's consider this file named lorem.txt:
$ cat lorem.txt
Lorem ipsum dolor sit amet
Consectetur adipiscing elit
Praesent molestie eros quis diam hendrerit
Id commodo augue porttitor
Donec quis nunc non ante gravida imperdiet ut in mi
This cat command will write the content of the lorem.txt file to the standard output, which will then be piped into the standard input of the head command, which will finally only output the first 2 lines of that file:
$ cat lorem.txt | head -n 2
Lorem ipsum dolor sit amet
Consectetur adipiscing elit
This cat command will write the content of the lorem.txt file to the standard output, which will then be piped into the standard input of the tail command, which will finally only output the last 2 lines of that file:
$ cat lorem.txt | tail -n 2
Id commodo augue porttitor
Donec quis nunc non ante gravida imperdiet ut in mi
Summary
Here's a summary of what you've learned in this lesson:
- There are three standard streams: stdin (
0), stdout (1), and stderr (2). - The
1>(or>) operator redirects the standard output into a file. - The
2>operator redirects the standard error into a file. - The
M>>operator redirects an output streamMinto a file and appends the data. - The
M>&Noperator redirects a streamMinto another streamN. - The
<operator redirects the standard input from a file. - The
|operator redirect the standard output of a command into the standard input of another command. - The
catcommand reads data from files or the standard input and writes the data to the standard output. - The
sortcommand sorts or merges lines of text. - The
uniqcommand reports or filters out repeated adjacent lines of text. - The
headcommand displays the firstNlines of text. - The
tailcommand displays the lastNlines of text.
Enjoying the courses?
I've made these courses completely free so anyone can learn from them. If they've helped you and you'd like to actively support the work behind BackendBrewery, you can leave a tip:
Support BackendBrewery