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

Is there a way that I can swap file names using perl? Heres an example:
*Two files: A and B
*B is a temp file and A is the final file
*My program updates file A; writes new content to the file
*Then I want to rename file B->A and A->B
This may seem weird but I am working with a program that reads in location data then displays objects using GIS. I can't seem to get the program to update a very dynamic object (refreshed every second), the problem is that the object keeps disappearing. I don't think that simple typing rename (file stuff) will work cause once you name B to A, then A already exists. I hope you get the gist. Any ideas?

Replies are listed 'Best First'.
Re: Swapping Files
by ikegami (Patriarch) on Sep 13, 2007 at 17:47 UTC
    If you want the change from one file to the other to be seemless, you could do
    use File::Copy qw( copy ); copy($old, "$old.bak") or die("Unable to backup \"$old\" to \"$old.bak\": $!\n"); rename($new, $old) or die("Unable to replace \"$old\" with \"$new\": $!\n");

    If the new and the old (original) file are on the same volume, there will never be a time where the file is missing or incomplete.

    Update: I think I misunderstood "B*" and that this doesn't answer the question.

Re: Swapping Files
by graff (Chancellor) on Sep 14, 2007 at 03:37 UTC
    Let me see if I understand:
    • before doing anything, files A and B are both already present
    • your program is supposed to modify the contents of A in some manner
    • after file A has been updated and closed, you want the existing content of B to have the file name "A", and you want the newly updated content of the existing "A" file to have the file name "B"
    Another way to phrase that last step, based on your second point, is that the existing "B" file (which had been considered "temp" data) becomes the new "A" file (no longer temp data?), whereas the existing "A" file, after being update by the script, becomes the new "B" file (to be considered henceforth as "temp" data?) That does seem strange, but... whatever.

    Usually, the only way to swap file names is by a three-step process:

    rename "A", "A.prime"; rename "B", "A"; rename "A.prime", "B";
    (though you'll want to come up wiht a "third-name" string that is certifiably guaranteed to be unique and novel, so you don't inadvertently obliterate some other file in the process.
      Her is the code, I keep getting the error on the rename command. Anyone know why?
      #!/usr/bin/perl #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~ #Reads in uavposition and outputs the uavpf.txt file # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~ use strict; use warnings; $\="\n"; my $img = '"http://updraft.unl.edu/~uas/uas/uas.png"'; for(;;){ #Open Placefile open OUT,'>',"/home/uas/public_html/uas/uaspf.txt.bak" or die +"Cannot Open File uavpf.txt.bak!"; #print placefile elements print OUT "Title: UAV GPS Position"; print OUT "Threshold: 999"; print OUT "RefreshSeconds: 2"; print OUT "Iconfile: 1, 22, 21, 10, 14, $img\n"; #read in UAV GPS lines #Open UAV GPS file open IN,'<',"/home/uas/Scripts/COORDS/uasposition" or die "Can +not Open File uavposition!"; while (my @gps = <IN>){ chomp @gps; my $ngps = @gps; my @uav = split(" ",$gps[$ngps-1]); my $lat1 = sprintf("%.5f", $uav[0]); my $lon1 = sprintf("%.5f", $uav[1]); my $head1 = sprintf("%.2f",$uav[2]); print OUT "Icon: $lat1, $lon1, $head1, 1, 1, Latitude: + $lat1 Longitude: $lon1 Heading: $head1 "; } close (IN); close (OUT); rename("uaspf.txt", "uaspf.txt.bak") or die"Unable to replace" +; sleep 2; }
        I do not know why, but here are some things to look at.

        Does printing the value of $! give you any clues?

        rename("uaspf.txt", "uaspf.txt.bak") or die"Unable to replace:$!\n";

        Alos, take a look at rename because there are portability issues with this function.