Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

Why?

share|improve this question
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 Jun 20 '12 at 18:19
    
@rahmu - True. I happen to be using zshell on OSX Lion. –  Nathan Long Jun 20 '12 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 Jun 20 '12 at 21:55
add comment

marked as duplicate by Michael Mrozek Jun 20 '12 at 18:40

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2 Answers

up vote 8 down vote accepted

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.

Update:

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.

share|improve this answer
    
Interesting. How would you remove all but the first line of a file, since head -1 foo.txt > foo.txt won't work? –  Nathan Long Jun 20 '12 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 Jun 20 '12 at 18:00
    
It's not something I'll do a lot. I just wondered if I was missing some obvious, better way. –  Nathan Long Jun 20 '12 at 18:02
    
This works: head -1 foo.txt | tee foo.txt –  Nathan Long Jun 20 '12 at 18:05
    
@NathanLong I just posted a solution using sed that will fit your requirements too. –  Levon Jun 20 '12 at 18:06
show 3 more comments

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.

share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.