Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Super Find critic needed

by Anonymous Monk
on Jun 30, 2003 at 12:22 UTC ( [id://270142]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

The below script does work and changes specific names on my web server where it starts from web root and changes ALL names in every directory. There are three names to change and the search and replace works recursively in every directory.

I would like as much input and/or critic on this script as possible so I can do the most efficient search and replace on my server. Please spare no feelings and give me as much input/critic to help make this script as best as possible.
use File::Find; use warnings; use strict; my @files; my $hit; my $line; my $ct = 0; my @data; sub NameReplace { if( $_ =~ /\.(?:html?|cfm|cfml|cgi|js|pl)$/) { my $name = $File::Find::name; open ( F, $name ) || warn "$!: $name\n"; while($line = <F>) { for $hit ($line =~ /(?:servername|servername\.aa\.company +\.zzzz\.com|servername\.aa\.company\.com)/gi) { $ct++; push (@files, $name); } } close F; } } find( \&NameReplace, "/webRootDirectory" ); foreach (@files) { open(DATA, "$_") or die "File does not open: $!"; @data = (<DATA>); close(DATA); open(DATA, ">$_") or die "File not open: $!"; foreach (@data) { s/servername\.aa\.company\.zzzz\.com/NEWNAME.\com/gi; s/\bservername\.aa\.company\.com\b/NEWNAME\.com/gi; s/\bservername\b/NEWNAME\.com/gi; print DATA $_; } close(DATA); } print "Total Count = $ct\n";

Replies are listed 'Best First'.
Re: Super Find critic needed
by BrowserUk (Patriarch) on Jun 30, 2003 at 12:42 UTC

    You should think seriously about what happens if your server crashes whilst processing lines 38 through 44 of your script.

    At that point you have opened the file, read the contents, closed and re-opened the file for output. If the server crashes, or even just the process gets interrupted, you have blown away the disc copy of the file and only retain its contents in memory. Even assuming you have backups, trying to work out which script were correctly modified, which ones have yet to be modified and which one was in the process of being modified when the interuption occurs can be extremely tiresome.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


      Okay if I am reading both of your comments correctly:
      if (open (F, ">$name")) { print F,$data; close(F); } #This part will be where I handle a server c +rash?? else { warn "...SERVER ERROR ETC.." }
      Please advise how I would handle a server problem/crash?

        By "server crash", I meant the machine (server or workstation) where the code is running, stops because of hardware failure, or power failure, or you knock the off-switch, or even because an administrator accidently kills your process while cleaning up zombies at 4 am. Ie. Events that you cannot detect from within your script.

        The basic mechanism to avoid this is to make a backup of the original before overwirting it with the modified version. The are several different sequences of copying, renaming, deleting and overwriting that you can use. Some of these are "better" than others, but I've yet to see one that completly eliminates the risks, though they reduce the window for failure to the point of reasonable risk.

        For a couple of neat way to use $^I (see Perlvar and perlrun -i) to get perl to backup your files for you, see My pattern for "in-place edit" for many files and Put your inplace-edit backup files into a subdir, both from Merlyn.

        Perhaps the best way to be safe, is to make a copy of the directory structure, run your script against that, and then copy the directory structure over the original when your sure it has been successful. Perhaps you are already doing (or intending to do) this, in which case you can ignore this advise.

        The other thing I noticed in your script is that every file will be over written regardless of whether any actual changes were made or not. This is likely to give you problems when you come to verify that the changes made where correct, or worse, make it hard to undo any mistakes as you won't know whether 1 file or every file was changed.

        There are many, many ways of writing your script, and many different philosophies on the best way to do it. Perhaps the best advice I can give you, is to sit down with your code, mentally or physically on paper, work through each step of the process and imagine what state your files will be left in if a powercut occurs at each step. Decide how much of a risk that presents in your system, and how much effort you should expend to prevent it from happening.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


        replace ">$name" by (e.g.) ">$name.$$" and do a rename "$name.$$",$name after the close(F).
Re: Super Find critic needed
by Skeeve (Parson) on Jun 30, 2003 at 12:41 UTC
    This comes to my mind:
    1. Why don't you do the replacements in NameReplace instead of pushing all filenames to a global array?
    2. I'd use
      s/\bservername(?:\.aa\.company(?:\.zzzz)?\.com)?\b/NEWNAME.\com/gi;
      in favour of your 3 replacements.
    I don't know whether or not this will be more efficient (untested, incomplete code):
    sub NameReplace { if( $_ =~ /\.(?:html?|cfm|cfml|cgi|js|pl)$/) { my $name = $File::Find::name; open ( F, $name ) || warn "$!: $name\n"; $data=join '',<F>; close (F); if ($data=~ s/\bservername(?:\.aa\.company(?:\.zzzz)?\.com)? +\b/NEWNAME.\com/gi) { if (open (F, ">$name")) { print F,$data; close(F); } else { warn "..." } } } }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://270142]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-23 08:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found