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.

This question already has an answer here:

I wanted to tail the last 100 lines of a file to the same file, but the command tail -n 100 file > file doesn't work, I assume because the stdout gets written to the file 'live', before everything was read from the original file.

Is there some way to pipe the output to something, that then keeps it until all 100 lines are there, and then outputs it to the file? Or just another way to shorten the file in this way?

share|improve this question

marked as duplicate by cuonglm, lgeorget, slm Jul 31 at 12:16

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.

    
I wouldn't mark it as a duplicate, as my problem has been wonderfully solved by sponge. Still, the link is good for people (like me) who want to know more about it. –  MadTux Jul 31 at 12:11

4 Answers 4

up vote 6 down vote accepted

sponge from moreutils is good for this. It will:

soak up standard input and write to a file

You use it like this:

tail -n 100 file | sponge file

to get exactly the effect you want.

share|improve this answer
    
Much nicer than less :) Also, thanks for introducing me to moreutils. That looks very useful. I think I'll accept this one. –  MadTux Jul 31 at 9:10

Of course, the moment I finally ask the question on SE, the answer comes to me. I think less does what I need, so I just write:

tail -n 100 file | less > file

share|improve this answer
1  
It's actually the redirection (>) that truncates the file, rather than the command you run - this won't (or at least shouldn't!) work. The shell opens and empties the destination before it even starts the commands you give. See the (slightly obtuse) description of output redirection in POSIX. –  Michael Homer Jul 31 at 9:28
1  
@illuminÉ: That is a neat point. So I should say that this does work very occasionally, but nondeterministically. –  Michael Homer Jul 31 at 10:14
    
@MichaelHomer Re this: really just an edge case, just thought of sharing it as it was insightful in context! Cheers! –  Amphiteóth Jul 31 at 10:23
    
OK, thanks for telling me. I think I'll downvote my own answer x) EDIT: I can't. Hmmm. –  MadTux Jul 31 at 12:09

In:

tail -n 100 file > file

The shell forks a process, opens file for writing in it, with truncation (that is making it an empty file) and then executes tail in that process. To open file without truncation, you can use the <> redirection operator instead:

tail -n 100 file 1<> file

The problem though is that there will be no truncation at all. That is, file will be overridden with its last 100 lines, but after those 100 lines, what was originally in the file will still be there. So you'd need to call another command to do the truncating after tail has finished.

{ tail -n 100 file; perl -e 'truncate STDOUT, tell STDOUT'; } 1<> file
share|improve this answer

You can do it this way:

printf '%s\n' "$(tail -n 100 file)" > file
share|improve this answer
    
Unless any lines contain more than one word or are blank. –  Michael Homer Jul 31 at 10:02

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