Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace a string in an existing file in Perl while not touching unchanged files

Tags:

file

perl

Using

perl -pi -e 's/pattern/replacement/g' $(find src -type f)

is nice, except for one thing: All files get overwritten, even those without any match. This is not good as I often keep many of them open in Emacs or Eclipse which then ask me boring questions. Is there a simple way how to prevent touching unchanged files (Something like using grep in find is too much work, especially for complex patterns).

like image 286
maaartinus Avatar asked Apr 01 '15 18:04

maaartinus


2 Answers

The very first thing -i after opening a file is to unlink it, so that means you can't use -i on the files you don't want to modify.

find src -type f -exec grep -Pl 'pattern' {} + |
   xargs perl -i -pe's/pattern/replacement/g'

Of course, grep can already perform recursive searches, so unless you need to use find to filter the results further than you indicated, you can use

grep -Plr 'pattern' src |
   xargs perl -i -pe's/pattern/replacement/g'

Note: cmd | xargs perl ... can handle more files than perl ... $( cmd ).

like image 75
ikegami Avatar answered Sep 25 '22 01:09

ikegami


Instead of passing every file to perl to be processed, preselect them yourself.

Find the files that have pattern in them:

grep -Plr 'pattern' src

Then use that instead of that find call:

perl -pi -e 's/pattern/replacement/g' $(grep -Plr pattern src)

Or even like this:

grep -Plr 'pattern' src | xargs perl -pi -e's/pattern/replacement/g'

This will also probably be faster because you're not processing files unnecessarily.

like image 25
Andy Lester Avatar answered Sep 23 '22 01:09

Andy Lester