Redirecting output
Bash provides a wide range of features for manipulating and redirecting output. Here we'll cover how to redirect output in Bash, including standard output (stdout
), standard error (stderr
), and how to pipe data between tools.
Input/Output streams
In command-line tools, stdin
, stdout
, and stderr
are standard streams that are typically used to handle input, output, and error messages, respectively.
stdin
is a standard input stream that is used to read data from the user or from another program: it is the input that a program receives. For example, when a program asks the user to enter data, the data is read from stdin
.
stdout
is a standard output stream that is used to display data to the user or to another program: it is the output that a program sends to the user or to another program. For example, when a program displays the result of a calculation, the result is sent to stdout
.
stderr
is a standard error stream that is used to display error messages or diagnostic messages to the user or to another program: it is the stream that a program uses to report errors, warnings, or other diagnostic information. For example, when a program encounters an error or a warning, the message is sent to stderr
.
In command-line tools, these streams are usually represented by file descriptors: stdin
is represented by file descriptor 0, stdout
is represented by file descriptor 1, and stderr
is represented by file descriptor 2. By default, the output of a command is sent to stdout
, while error messages are sent to stderr
.
Standard Output (stdout) redirection
Standard output is the default output channel for command-line programs, where the output is displayed on the terminal. However, sometimes it is desirable to redirect the output to a file instead. This can be done using the greater-than symbol (>
) followed by the name of the file to which the output should be redirected.
For example, to redirect the output of a command to a file, use:
This will redirect the output of ls
to filelist.txt
instead of displaying it on the terminal.
This will replace the content of the target file!
It is also possible to append output to an existing file by using the double greater-than symbol (>>
). For example:
This will append the output of ls
to the end of filelist.txt
.
The output of a program can be suppressed and discarded entirely by redirecting it to the special file /dev/null
. The null file accepts any amount of data, and immediately discards it.
Standard Error (stderr) redirection
Standard error is the default channel for error messages and diagnostics, which are displayed on the terminal. However, it is also possible to redirect standard error to a file.
To redirect standard error, use the number 2 followed by the greater-than symbol (>
). The number 2 represents the standard error stream.
For example, to redirect the standard error of a command to a file, use:
This will redirect any error messages generated by grep
to errors.txt
.
This will replace the contents of errors.txt
, and just like redirecting stdout
, you can use the >>
operator to append, instead:
Also just like how the stdout data can be suppressed by sending it to the
/dev/null
file, data on stderr
can also be suppressed:
Combining outputs
The output of one stream can be combined with the output of another by using the >&
option. This allows us to combine stdout
and stderr
for instance:
The stdout
stream has the id of 1
so we're sending stderr
to stdout
which will appear on the console.
Of course, the combined output can also be redirected:
This will log both the result of grep and any errors together.
Piping data between tools
One of the most powerful features of Bash is the ability to pipe data between tools. Piping allows the output of one command to be used as the input of another command, without the need for intermediate files.
To pipe output to another command, use the vertical bar (|
) symbol. For example:
It is possible to chain multiple commands together using pipes. For example:
This takes the output of ls
, searches for test
, and then uses the wc
tool (word count) with the line option (-l
) to count how many lines. It will print the number of files with test
in the name!
These features provide a powerful and flexible way to manipulate and process data on the command line, and can help streamline many common tasks.
Incorporating other tools
Now that we can connect output from one command to another, we can use many built-in tools for data manipulation.
In the following examples, we use echo
and cat filename
as the source of data for demonstration purposes, but remember the beauty of piping between commands - the data can come from any other commands that output text, like ls
, ps
, grep
, etc!
The "tr" command
The tr
command in Linux is used to translate or delete characters from standard input and write to standard output. It can also be used to replace a set of characters with another set of characters.
The basic syntax of the tr
command is as follows:
where set1
is the set of characters to be translated, and set2
is the set of characters to translate set1
into. If set2
is shorter than set1
, the extra characters in set1
are deleted from the output.
Some common options for the tr
command include:
-c
: complement the set of characters inset1
-d
: delete characters inset1
-s
: squeeze repeated occurrences of characters inset1
into a single occurrence
Here are some examples of how you can use the tr
command in a payload:
Translate all lowercase letters to uppercase:
Output: HELLO WORLD
Delete all vowels from a string:
Output: hll wrld
Replace all spaces with tabs:
Output: hello world
Complement the set of characters in a string (i.e., replace all non-alphanumeric characters with a space):
Output: hello world
(Note the space at the end.)
The "sed" command
The sed
command (short for "stream editor") is a powerful text-processing tool. It is used to manipulate, transform, and replace text in a file or a stream of text. It works by reading a file or stream line-by-line, making specified modifications, and then outputting the modified text.
The basic syntax of the sed
command is as follows:
or chained with a pipe,
Here are some examples of how you can use the sed
command in a payload:
Replace a string in a file:
This command will replace all occurrences of old_text
with new_text
in the filename
file. The -i
option specifies that the changes should be made in-place, meaning that the original file will be modified.
The output will be sent to newfile
.
Delete a line from a file:
This command will delete the second line from the filename
file. The d
command is used to delete lines.
The output will be sent to newfile
.
Insert a line before or after a matching pattern:
These commands will insert new_text
before or after the first occurrence of pattern
in the filename
file, respectively. The i
command is used to insert text before a matching pattern, while the a
command is used to insert text after a matching pattern.
The output will be sent to newfile
.
Replace a string in a file only in lines matching a pattern:
This command will replace all occurrences of old_text
with new_text
only in the lines that match pattern
in the filename
file. The s
command is used to substitute text, and the /pattern/
specifies that the substitution should only be made in lines that match the pattern.
The output will be sent to newfile
.
These are just a few examples of how you can use the sed
command in a bash script. There are many more options and commands available that you can use to manipulate text in a file or stream.
The "awk" tool
awk
is another powerful text-processing tool. It is used to process and manipulate text files that are formatted in a specific way. It can extract and print specific fields, perform calculations, and search and replace text.
The basic syntax of the awk
command is as follows:
or using pipes:
Here are some examples of how you can use the awk
command in a shell script:
Print specific fields from a file:
This command will print the first and third fields from the filename
file, separated by a space. The fields are separated by whitespace by default.
The output will be sent to newfile
.
Print lines matching a pattern:
This command will print all lines from the filename
file that match the pattern
. The /pattern/
specifies the pattern to search for, and the { print }
specifies the action to perform on matching lines.
The output will be sent to newfile
.
Perform calculations:
This command will add up all the numbers in the first field of the filename
file and print the total at the end. The END
keyword specifies that the action should be performed after all lines have been processed.
The output will be sent to newfile
.
Search and replace text:
This command will search for all occurrences of old_text
in each line of the filename
file and replace them with new_text
. The gsub
function is used to globally substitute text, and $0
refers to the entire line.
The output will be sent to newfile
.
These are just a few examples of how you can use the awk
command in a shell script. There are many more functions and options available that you can use to manipulate text in a file or stream.
Summary
These tools provide a powerful and flexible way to manipulate and process data on the command line, and can help streamline many common tasks.
Not every command line tool uses stdout and stderr in the expected ways, but the vast majority of them do. Being able to manipulate and redirect the data streams from tools enables chaining for complex behavior and creating entirely new tools.
Last updated