in reply to Need one-liner to s///g in all sub-dirs

Making use of other shell utilities, this is the most immediate solution which comes to mind for me:
 
find . -type f -exec perl -pi.bak -e 's/old/new/g' {} \;

 
If you want to do it 'all in Perl', find2perl makes it easier still:
 
rob@budapest:~$ find2perl . -type f -exec perl -pi.bak -e 's/old/new/g +' {} \; #!/usr/bin/perl-5.005 eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if $running_under_some_shell; require "find.pl"; # Traverse desired filesystems &find('.'); exit; sub wanted { (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _ && &exec(0, 'perl','-pi.bak','-e','s/old/new/g','{}'); } sub exec { local($ok, @cmd) = @_; foreach $word (@cmd) { $word =~ s#{}#$name#g; } if ($ok) { local($old) = select(STDOUT); $| = 1; print "@cmd"; select($old); return 0 unless <STDIN> =~ /^y/; } chdir $cwd; # sigh system @cmd; chdir $dir; return !$?; }

 
If you then wanted to take out the forking of a separate perl process for the editing of each file, then I would recommend changing the &exec() call to something similar to that posted by tachyon recently at Inplace Editing.
 

 
Ooohhh, Rob no beer function well without!

Replies are listed 'Best First'.
Re(2): Need one-liner to s///g in all sub-dirs
by dvergin (Monsignor) on Aug 25, 2001 at 07:40 UTC
    dvergin struggles to follow the thread...
    Assuming I've already made the backups. What does find . -type f -exec perl -pi.bak -e 's/old/new/g' {} \; do that my suggestion does not do.

    And why '-p' instead of '-n'.

    Oops! Found another switch. I now submit: %perl -nie 's/old/new/g' ./*/*

      Okay, the find . -type f -exec perl -pi.bak -e 's/old/new/g' {} \; command finds all files under the current directory and passes them through the command perl -pi.bak -e 's/old/new/g' {} which the {} delimiter is replaced with the filename. This I feel is the easiest way to find all files within a given directory tree and pass them through the perl command for in-place modification. Yes it isn't a "pure-Perl" solution, but sometimes reinventing the wheel isn't the best approach to a problem. And that too, as always, TIMTOWTDI.
       
      The -n and -p command line switches are similar, both creating a loop similar to this around the passed -e code:
       
      # -n switch execution # LINE: while (<>) { .... # your command is executed here }

       
      The difference is that the -p causes an additional print statement to be incorporated into the loop which is important so that your modified code is printed back out to the file. For example:
       
      # -p switch execution # LINE: while (<>) { .... # your command is executed here } continue { print; } }

       
      Assuming you have already made your backups, you can remove the -i.bak switch which would made a backup of modified files, moving then to name.bak.
       

       
      Update : The Perl command line switches are well documented at perlman:perlrun with additional examples.
       

       
      Ooohhh, Rob no beer function well without!
        I have indeed read perlman:perlrun (several times this evening) and I recognize the code you are quoting from that source. I am sure all this seems pretty trivial to folk who use it all the time -- but it is daunting to the uninitiated. And frustrating. I could have writen several scripts to do this task using different and interesting approaches and taken a looong walk in the time I have spent on this trying to get some experience with command line switches. I am presuming upon your patience...

        Okay: Encourged by your insistence, I finally found this bit in Camel 3, page 496: The -p loop also contains an implicit select(ARGVOUT); for each file.   perlrun just says, "Note that the lines are printed automatically." It omits to say at that point "to the file in question". It's probably there somewhere. And it's clear once you know it. I just missed it.

        All of which brings my to my tired question (revised a little each time). And I ask again because this part is still not clear. Assuming that the files are already backed up, does not this simple line: %perl -pie 's/old/new/g' ./*/* do everything I need without the use of find.... When I am doing things on unfamiliar turf, I like (if possible) to keep it simple and clear.

        Update: Still reading... perlrun does contain the explanation of the implicit select(ARGVOUT);. But, as in Camel 3 (which simply reprints the whole section) it is under the -i, not -p. IMHO, the briefer code given under -p is misleading since it claims to explain what -p does but fails to mention the implicit 'select'. This is a crucial detail and the reason I deliberately chose not to use it at first. I had no need to print to STDOUT (which is what the code under -p, as given, would do).