Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Need to change, oh, every file at once?

by z3d (Scribe)
on Jan 22, 2002 at 04:07 UTC ( [id://140536]=CUFP: print w/replies, xml ) Need Help??

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 ./ {} \;

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 ./
    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. <- 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."

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://140536]
Approved by root
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-05-19 08:33 GMT
Find Nodes?
    Voting Booth?

    No recent polls found