Linux command line tricks you need to know: IO redirection and piping

Feb 14, 2012

The linux command line has a rich set of utilities and functionality. One of its beauties is that there are many utilities with a simple purpose that are in themselves very useful, but can also be combined to do an amazing array of jobs. This is a fundamental part of linux with tricks built into the bash command line shell to make that very easy.

In this post I'm going to be talking about two such tricks that every command line warrior must know: IO redirection, and piping. Whether you're writing shell scripts, or doing one-off commands on the command line, both are very useful.

IO Redirection

IO redirection is useful, for example, if you want to store the output of a program for later reference. I like to log almost everything, so in my crontab instead of my output going into a black hole I redirect it to a file in my logging directory using the ">" operator.

To redirect the standard output of a command to a file:

echo "hey" > filename

This will create a new file or wipe the contents of an existing file and write the output of the command to it. If you would rather append to the file if it already exists use:

echo "how are you?" >> filename

Here's an example with a little bit more import. To do a regex substitution and save the results in a new file:

sed 's/obama/palin/g' liberal.txt > conservative.txt

What about input?

You can use a file as the source of input to any command. The "<" operator will send the contents of a file to the standard input of a command.

sort < christmas_list.txt

This will send the contents of the file "christmas_list.txt" to the "sort" command, which will display the sorted results. You can also chain the different io redirection operators. For example:

sort < christmas_list.txt > sorted_christmas_list.txt

What about standard error?

You can also redirect the standard error (stderr) output if you want to capture error messages.

command 2> error.log

This will redirect the stderr to a file. "2" always represents the standard error ("1" represents the standard output). If you want to redirect both stdout and stderr to the same file:

command > filename 2>&1

Here's an example of a poor man's daemonize that'll run a command in the background and capture the standard output and error to a file.

nohup command > nohup.log 2>&1 &

nohup (short for nohangup) makes the process ignore interrupts, quit signals, and hangups that may accidentally cause the process to abort. The final "&" means to run it in the background.

The abyss: /dev/null

If you don't care to see the output you could redirect the output to /dev/null.

command > /dev/null 2>&1

/dev/null is a special file that discards all the data written to it.

Pipes

Pipes are another useful way to manipulate the input and output of a program. They are used to send the output of one program to the input of another.

To pipe something use the pipe "|" character and the standard output of one command will be sent to the standard input of the next command.

As a quick example, you can pipe the "history" command through "grep" to see only the history you're interested in.

history | grep "python"

This will only display your previous python commands for the current session. To pipe the bash history of your session through the "more" program, which allows you to page through a screenful of output at a time, you use the following:

history | more

The same can be done with any program that may produce a large amount of output (eg. "ls", "find" etc).

More examples

Sort the contents of a file alphabetically and save the result to a new file.

cat christmas_list.txt | sort > christmas_list.txt

Display processes with the highest memory usage:

ps aux | sort -nrk 4 | head

If you want the output to go to both the display and to a file:

command | tee filename

Simple tools, but limitless possibilities

I'm only really scratching the surface with this introduction. A really cool feature I didn't even touch upon are named pipes. The amount of things you can do on the command line makes linux a deep user experience because there's so much you can discover. I'm constantly discovering great new tricks I didn't know about before. The possibilities are limitless.