9

I just ran

cat /opt/webapplications/Word/readme.log | grep -v 'Apple'

and I got the output on the cli that I was expecting, which was all the lines in readme.log that did not contain 'Apple'...

Next I ran...

cat /opt/webapplications/Word/readme.log | grep -v 'Apple' > /opt/webapplications/Word/readme.log

However, /opt/webapplications/Word/readme.log is blank.

Can anyone explain to me why this happened, or the correct way I should have gone about this?

2

2 Answers 2

15

This happened because the first thing > does is to create the file it wants to write to - and if the file already exists, its contents will be deleted. (Also, there's no need at all to use cat in your statement since grep works on files, not just on STDIN.)

The correct way to do this is to use a temporary file either to read from or to write to. So either

cp /opt/webapplications/Word/readme.log /tmp/readme.log
grep -v 'Apple' /tmp/readme.log > /opt/webapplications/Word/readme.log

or

grep -v 'Apple' /opt/webapplications/Word/readme.log > /tmp/readme.log
mv /tmp/readme.log /opt/webapplications/Word/readme.log

would work.

2
  • or just use >>
    – avtomaton
    Sep 3, 2020 at 10:40
  • @avtomaton In the circumstances posted in the question, that would cause an infinite loop.
    – Jenny D
    Sep 5, 2020 at 11:26
2

When doing redirect into the same file (>), shell may create/truncate the file before the cat command is invoked and the input is read (see: Why doesn't “sort file1 > file1” work?). If you want to filter the file, it's better to redirect the output into different file, or avoid redirection at all, for example:

grep -v 'Apple' readme.log | tee readme.log

The better and safer way is to use in-place editors which are designed for that kind of operations, e.g.

sed -i '.bak' '/Apple/d' readme.log

or use ex (part of Vim):

ex +g/Apple/d -cwq readme.log

Related:

You must log in to answer this question.

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