Possible Duplicate:
IO redirection and the head command

I just wanted to remove all but the first line of a file. I did this:

head -1 foo.txt

... and verified that I saw only the first line. Then I did:

head -1 foo.txt > foo.txt

But instead of containing only the first line, foo.txt was now empty.

Turns out that cat foo.txt > foo.txt also empties the file.


  • 2
    A more interesting question (yet slightly more pedantic) would be to know if the evaluation order is defined in POSIX or is it implementation-specific.
    – rahmu
    Commented Jun 20, 2012 at 18:19
  • @rahmu - True. I happen to be using zshell on OSX Lion. Commented Jun 20, 2012 at 18:21
  • 1
    @rahmu POSIX does specify the order but it doesn't need to because if you think about it for just a moment, you'll realize that the shell is the one that does the redirections and it has to do them before running the command, since it will be too late to do it after the command has already started. Add that bit of common sense to the fact that the > operator includes truncation and this behavior becomes very logical.
    – jw013
    Commented Jun 20, 2012 at 21:55

2 Answers 2


Before the shell starts processing any data, it needs to make sure all the input and output is squared away.

So in your case using > foo.txt basically tells the system: "create a (new) file named foo.txt and stick all the output from this command into that file".

The problem is, as you found out, that that wipes out the previous contents.

Related, >> will append to an existing file.


Here's a solution using sed, handle with care:

 sed -i '2,$d' foo.txt

It will delete lines 2 to "last" in-place in file foo.txt. Best to try this out on a file you can afford to mess up first :)

This slightly modified version of the command will keep a copy of the original with the .bak extension:

 sed -i.bak '2,$d' foo.txt

You can specify any sequence of characters (or a single character) after the -i command line switch for the name of the "backup" (ie original) file.

  • Interesting. How would you remove all but the first line of a file, since head -1 foo.txt > foo.txt won't work? Commented Jun 20, 2012 at 17:55
  • @NathanLong Off the top of my head, I'd just use a different temporary file for the output and then rename it. Or is this something you are going to do over?
    – Levon
    Commented Jun 20, 2012 at 18:00
  • It's not something I'll do a lot. I just wondered if I was missing some obvious, better way. Commented Jun 20, 2012 at 18:02
  • 1
    This works: head -1 foo.txt | tee foo.txt Commented Jun 20, 2012 at 18:05
  • 1
    Please don't recommend sed -i. It's not portable and probably doesn't even work correctly on links. Non-portable alternatives include cmd file | sponge file. Portable alternatives include ed (ed is a file editor; sed is a stream editor, not a file editor), which has more or less the same commands as sed, or a temporary file.
    – jw013
    Commented Jun 20, 2012 at 21:59

Because the shell that you use to invoke cat does the redirection indicated by >.

The shell (bash, zsh, ksh, dash, whatever) reads the command cat foo.txt > foo.txt. The shell has to set up the redirection indicated by > foo.txt. > means to start writing the file from the top, >> would mean to append to foot.txt.

By the time the shell actually gets cat running, foo.txt has disappeared.

Not the answer you're looking for? Browse other questions tagged .