Now that you know how to use pipes in between commands, you can do a lot without worrying about storing data in files. But what if you want to keep something in a file? Let's say you want to:
- share a file with other people
- keep data for future reference
- build up a log file over time
- do further work on a file in a text editor like Nano or a spreadsheet application
- use data with some other tool which isn't very good at accepting standard input
- pull data out of a file and send it to the standard input of a command which doesn't know how to deal with files on its own
This is where
>>, and their sibling
< come into play.
If you have output you want to store in
filename, just tack
> filename onto the end of your command line:
As long as you have permission to write to the specified filename, you'll wind up with a file containing the pipeline's output. I like to remember that the
> character looks sort of like a little funnel.
Sometimes, you want to stash your output at the end of an existing file. For that, just use
This is often handy for accumulating log files over time, or for building up a collection of data with multiple pipelines.
Lastly, suppose you want to take the contents of a file and send them to the standard input of some command? Just use
command < filename.
The little funnel is going the other direction now, from the file back into the command.
This one can be harder to remember, because it doesn't come up nearly as often as the first two. Most utilities you'll encounter are written so that they can read files on their own. Still, it can be a powerful trick that saves you a bunch of contortions, especially once you get into writing your own scripts and utilities.
Before long, you might find it natural to try and overwrite the contents of some file by running a command on it and redirecting the output of that command to the same file.
nl is a command to number the lines of its input. Suppose I decided that the version of a file I've already saved would be better with line numbers on it? I might be tempted to try something like the following:
Ouch. The whole file seems to be gone. What's happening here? It turns out that the shell opens
file.txt for writing before it ever executes the command pipeline! This makes a kind of sense once you know about it, but it's not especially obvious at first.
Fortunately, there's an easy workaround in this case - use
This does two things:
- print its stdin back to stdout
- write its stdin to a given filename
tee file.txt isn't executed until after
nl file.txt has already run, you wind up with the desired outcome.