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

My script runs without error but is not making changes to the files that it finds.
And, there are two lines in the master file and it appears the loop is not getting to the second line.
And, it is not renaming any files to .bak

#!/usr/bin/perl use strict; use warnings; use File::Find; my $opsys = $^O; my $hostname = qx |uname -a| or die("Can't get info for hostname: $!\n +"); my @uname = split (/\s/, $hostname); my $searchdir = '/dir/etc-test'; print ">>> Operating System: $opsys" . "\n"; print ">>> Hostname: $uname[1]\n"; open (my $FH, '<', 'ipmastr') or die "Could not open 'ipmaster' : $!"; + while (<$FH>){ chomp; my ($ipold, $ipnew, $nmold, $nmnew, $dgold, $dgnew, $ns1old, $ns1n +ew, $ns2old, $ns2new, $ip6old, $ip6new) = split (/\t/); $^I = '.bak'; find(\&wanted, $searchdir); sub wanted { my $filename = $File::Find::name; print "$ipold - Filename is: $filename\n"; return unless -f $filename; open (FR, '<', '$filename') or print "Could not read $filename +\n" && return; my @lines = <FR>; close (FR); open (FW, '>', '$filename') or print "Could not open for write + $filename\n" && return; for ( @lines ) { s/$ipold/$ipnew/g; print FW $_; } close FW; } } close $FH;
MY OUTPUT
user@host:erl: ./update-text.pl
>>> Operating System: linux
>>> Hostname: host.com
10.41.37.99 - Filename is: /dir/etc-test
10.41.37.99 - Filename is: /dir/etc-test/resolv.conf
10.41.37.99 - Filename is: /dir/etc-test/sysconfig
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts/ifcfg-eth0
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts/ifcfg-eth1
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts/ifcfg-lo
10.41.37.99 - Filename is: /dir/etc-test
10.41.37.99 - Filename is: /dir/etc-test/resolv.conf
10.41.37.99 - Filename is: /dir/etc-test/sysconfig
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts/ifcfg-eth0
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts/ifcfg-eth1
10.41.37.99 - Filename is: /dir/etc-test/sysconfig/network-scripts/ifcfg-lo

Replies are listed 'Best First'.
Re: Need assistance updating text files with Perl
by Anonymous Monk on Dec 31, 2009 at 17:15 UTC
    My script runs without error but is not making changes to the files that it finds.

    single quotes do not interpolate, so print '$filename' literally prints $filename where you wanted /dir/etc-test.... See perlintro. As a rule only use quotes for creating new strings, so

    open my( $FR ), '<', $filename ...

    And, it is not renaming any files to .bak

    Using $^I only works with magic filehandle, see perlrun -i, $^I why this symbol does not work ?

Re: Need assistance updating text files with Perl
by MidLifeXis (Monsignor) on Dec 31, 2009 at 18:18 UTC
    open (FR, '<', '$filename') or print "Could not read $filename +\n" && return; my @lines = <FR>; close (FR); open (FW, '>', '$filename') or print "Could not open for write + $filename\n" && return; for ( @lines ) { s/$ipold/$ipnew/g; print FW $_; } close FW;

    Can I also suggest writing to a temporary file, and then renaming? If you overwrite the old file, you risk a power outage / system failure / SIGINT leaving you with an empty or corrupt file.

    --MidLifeXis

      What would the code look like for your suggestion to write to a temp file and then rename?

      I got the old new replacements to work now by removing the quotes in my two open statements.

      I am still having an issue with my loops. When I run the script it touches every file found two times (not necessary) and I am not sure how I told it to do that.

      Also it is not advancing to the next line in the master file as the print line in the output is not showing the ip address from the second line. Only the first line all the way down.
Re: Need assistance updating text files with Perl
by Marshall (Canon) on Jan 01, 2010 at 01:33 UTC
    I noticed that you defined a subroutine within the while(){}. This probably doesn't do what you think that it does.
    #!/usr/bin/perl -w use strict; foreach (1..3) { printx2 ($_); sub printx2 { my $num = shift; print $num *2,"\n"; } } # printx2() works here also! printx2 (32); # the above did NOT make a "private sub" to # the foreach statement. A subroutine name # has package scope. __END__ Prints: 2 4 6 64 Move sub printx2() out of the curly braces. This reduces the amount of indenting. The meaning doesn't change. foreach (1..3) { printx2 ($_); } printx2 (32); sub printx2 { my $num = shift; print $num *2,"\n"; }