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

I'm using the Config::IniFiles module to update some existing ini files, and cannot get it to replace the existing ini with the updated one. It leaves the temporary file (ending in "-new") and doesn't rename it to the original name. As a test, I tried to rename it myself, using unlink/rename, as commented-out in the code, but that didn't work either, nor did I get the "die" messages.

I'm still new at Perl, so I'm sure it's something pretty basic but, after looking through the various sites all morning, I'm lost. Your help is hugely appreciated!

The relevant code snippet follows:

sub updtDescrip() { my $tmpPthFil = "$demoQcPth"."tmp_drs_demoqc$mm$yy$c\.ini"; # Get a temp. ini object $tmpIni = new Config::IniFiles( -file => $tmpPthFil, -allowedcomme +ntchars => '*', -nocase => '1'); if (!defined($tmpIni)) { &errMsg2 ("Failure re-accessing \"tmp_\" DRS file. Program +will abend."); &errMsg1 (" File: $tmpPthFil"); &abend (); }; my $tmpVal = $tmpIni->val( "Application", "Description"); # + Section, Key if (!defined($tmpIni)) { &errMsg2 ("The \"Description\" value cannot be found. Progr +am will abend."); &errMsg1 (" File: $tmpPthFil"); &abend(); }; # insert, e.g., "1104 / " before the descri +ption $tmpVal =~ s/(\w+)/DemoQC $mm$yy \/ $1/; # $tmpVal = $tmpIni->setval( "Application", "Description", $tmpVal); # +Section, Key if (!defined($tmpIni)) { &errMsg2 ("Resetting the \"Description\" value failed. Prog +ram error. Program will abend."); &errMsg1 (" File: $tmpPthFil"); &abend(); }; # Rewrite the ini file $tmpIni->RewriteConfig($tmpPthFil); if (!defined($tmpIni)) { &errMsg2 ("Failure re-accessing \"tmp_\" DRS file. Program +will abend."); &errMsg1 (" File: $tmpPthFil"); &abend (); }; printf(" DemoQc descrip: $tmpVal \n tmpPthFile: $tmpPthFil\n"); # unlink("$tmpPthFil") or die ("Failure deleting: $!"); # rename("$tmpPthFil\-new", "$tmpPthFil") or die ("Failure renaming +: $!"); };

Replies are listed 'Best First'.
Re: Problem Modifying Files
by Random_Walk (Prior) on Sep 22, 2004 at 16:34 UTC

    When you tried to rename it using unlink/rename was the original file actualy unlinked after your script ran ? Are you sure this bit of code it actualy being called ? Perhaps you can add some print statements to see that the code is getting to the rename. Is the new .ini-new actualy being updated ? Can you run the following test ok ?

    #!/usr/bin/perl -w use strict; use File::Copy; my $new="mytest"; open NEW, ">$new" or die "I can not open file to write: $!\n"; print NEW "this is a test"; close NEW; copy ("$new", "$new.new") or die "can't make a copy: $!\n"; unlink $new or die "can not unlink it: $!\n"; rename ("$new.new", "$new") or die "cant move it: $!\n"; unlink $new or die "can not unlink it at the end: $!\n";

    Cheers,
    R.

      Hi Random:

      Thanks for your help.

      In answer to your questions: The original file was not unlinked. I'm sure the code was being called, as the "printf(" DemoQc descrip: $tmpVal \n tmpPthFile: $tmpPthFil\n");" lines were displayed. The ini-new file was updated.

      Interesting issue, though . . . . I ran your code, changing only the "my $new="c:\\temp\\mytest";" line (so I'd be sure where the files were going), but nothing was created. I'm on Win2K, so I'm now wondering if there's something going on at a system level. I'm really grasping at straws with that one. Any ideas?

      Thanks!

        You are using \\ in interpolation context, and then again:

        $new = "c:\\temp\\mytest"; # c:\temp\mytest -- ok so far open NEW, ">$new"; # c:<tab>emp<return>ytest -- oops

        Try it using non-interpolating, single quotes. For example:

        $new = 'c:\\temp\\mytest';

        If you run the code in the temp dir then you can just leave the name without a path and remove concerns about handling of \\. I am on slowaris here so I can't test now but I think you can use c:/this/file/spec paths in win Perl and perl will handle the conversion for you, may be worth a go. I have also added some verbosity to the test to narrow down the failure. No time to test it here but it should run...

        #!/usr/bin/perl -w use strict; use File::Copy; my $new="mytest"; open NEW, ">$new" or die "I can not open file to write: $!\n"; print NEW "this is a test"; close NEW; if (-f "$new") { print "Created $new file just fine\n"; }else{ print "Did not create $new, most odd\n"; exit 1; } copy ("$new", "$new.new") or die "can't make a copy: $!\n"; if (-f "$new.new") { print "Copied $new to $new.new file just fine\n"; }else{ print "Could not copy $new, most odd\n"; exit 1; } unlink $new or die "can not unlink it: $!\n"; if (-f "$new") { print "Failed to delete $new\n"; exit 1; }else{ print "Deletion works too\n"; } rename ("$new.new", "$new") or die "cant move it: $!\n"; if (-f "$new") { print "Renamed $new.new to $new file just fine\n"; }else{ print "Rename failed, most odd\n"; exit 1; } unlink $new or die "can not unlink it at the end: $!\n"; if (-f "$new") { print "Failed delete second $new, that is realy odd\n"; exit 1; }else{ print "Deletion works again\nEverything looks fine\n"; }

        Cheers,
        R.

      Hi,
      I used this module once on win32 and remember that there were some problems using it.. If I created new IniFiles objects with the -file parameter and the file supplied did not exist or if the file existed but was empty, then the the new() method just didn't return any object..

      For the -file parameter to work 1) the ini file had to exist and 2)there had to be atleast one section in the file!?..weird..

      I guess there is some "UNIX-to-Windows"-issues" that is causing the problem in the module..

      use Config::IniFiles; use strict; updtDescrip(); sub updtDescrip() { my $tmpPthFil = q(test.ini); #Create ini file with one dummy section if 1)it does not exist + or 2)exists but zero size if (not -e $tmpPthFil or ( (-e $tmpPthFil) and (-z $tmpPthFil) ) + ) { open INI, ">$tmpPthFil"; print INI "[Ini]"; close INI; } #Now the -file option is working ok. my $tmpIni = new Config::IniFiles( -file => $tmpPthFil, -allowedco +mmentchars => '*', -nocase => '1', ); #Output sections that already exist in ini file. foreach ($tmpIni->Sections) { print "Section:$_\n"; } #Add a new section and parameter with a value $tmpIni->newval('apps', 'app1', 'bull.exe', ); $tmpIni->newval('apps', 'app2', 'bull2.exe', ); #Set already existing parameter value in a section $tmpIni->setval ('apps', 'app1', 'app99.exe'); #Retrives existing parameter value in a section my $app = $tmpIni->val ('apps', 'app1'); print "\nApp1 is $app"; #Save config file $tmpIni->WriteConfig ($tmpPthFil); } config file after run: [ini] [apps] app1=app99.exe app2=bull2.exe

        Thank you all for your help!

        It turned out to be a "permissions" issue. I added code to "manually" unlink the old file and rename the new, and $! gave the response "Permission denied".

        It's funny, though, that the module set permissions that allowed me to create the ini, but not to delete/rename it!

        For some reason, I didn't get the errors from the module in my error handling code below. I'm not sure if it's the module or my code, but I <think> my code's o.k.

        Again, my thanks!

        sub errMsg1() { printf "@_\n"; &msgLog ("@_\n"); &stdErr ("@_\n"); printf @Config::IniFiles::errors; for my $line (@Config::IniFiles::errors) { &stdErr ("\t$line\n"); printf "$line\n"}; };