http://qs1969.pair.com?node_id=140536

Had a boss show me this one once and it really opened my eyes up. I just never paid attention to those "other" switches you could add to the shebang. What he showed me is a way to combine a two line perl script to a find to change every single file in a directory structure at once (The actual scenario was we had a client lose their hostname through shear incompetence and we had to compensate with what they could get from internic - and we needed to change every file in their web site simultatneously because they also had a practice of hardocding URL's into their site - if it isn't complex, it isn't life...).

OK, here's the code, followed by the explanation...

#!/usr/bin/perl -pi $_ =~ s/sometext/someothertext/mg;

Yeah, that's the whole script. The secret is in the -pi. Check out the perldoc perl pages for more information - this form replaces the page entriley. You can also set it so perl writes a backup file as it goes too. To use the script, just do a find exec, like so:

find ./ -name "*" -type f -exec ./somescript.pl {} \;

Believe me, this has been a lifesaver. Like moving netscape server instances between servers so you don't have to retweak....



Zed? Zed's dead, baby, Zed's dead.

Replies are listed 'Best First'.
Re: Need to change, oh, every file at once?
by BazB (Priest) on Jan 22, 2002 at 04:27 UTC

    A slight modification on this is the following line shell script/perl one-liner that came from a short discussion on the LUG for an easy way to change email addresses in every page on my site:

    for i in *.html; do perl -wpi.bak -e 's/oldusr\@olddomain/newusr\@newdomain/g' $i; done
    I think I can say this is the first snippet that made me think - wow! Perl rocks! :-)

    I'm sure TMTOWTDI, but I still press this code into service now and again.

Re: Need to change, oh, every file at once?
by ariels (Curate) on Jan 22, 2002 at 12:49 UTC
    This way of using `find' is inefficient: it spawns a new Perl process for every file processed. Why not use xargs? (Also, ``-name "*"'' does nothing, so you could just lose it)
    find ./ -type f | xargs ./somescript.pl
    starts the least number of processes. More than one process may be started if the length of the command line grows beyond what's permitted.
      -name * is redundant with GNU find, other finds such as Solaris require this.

      UPDATE: Sorry, Sun requires a PATH which is optional for GNU.

      --
      perl -pe "s/\b;([st])/'\1/mg"

Re: Need to change, oh, every file at once?
by belg4mit (Prior) on Jan 22, 2002 at 04:50 UTC
    Congratulations, you can make toast!

    Not to discourage you in anyway, but this is a very well-known idiom. Very cool, and also one of the things I enjoyed when I first encountered perl. Something that might come in handy with this if you have not yet seen it is File::Find

    --
    perl -pe "s/\b;([st])/'\1/mg"

Re: Need to change, oh, every file at once?
by sheriff (Sexton) on Jan 25, 2002 at 19:45 UTC
    If you wanna be *REALLY* cool using Perl on the command line, have a play with PPT, that replaces common unix-esque utilities with perl equivs.

    http://sourceforge.net/projects/ppt <- PPT on sourceforge.

      I know this is quickly going off topic, but is PPT still active? Fun idea, but the CVS is over a year old. Unless (gasp) they finished what they set out to do...



      "I have never written bad code. There are merely unanticipated features."