Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Sequentially numbering output files rather than overwriting an existing file

by TJCooper (Beadle)
on Jan 08, 2014 at 14:53 UTC ( [id://1069813]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I'm currently working on the following script:

use strict; use warnings; my $usage = "Usage: $0 <infile.txt>\n"; my $infile = shift or die $usage; use File::Basename; my $DIR = dirname($infile); my $outfile = $DIR . "/Results.txt" or die $usage; open (my $data, "<", $infile) or die "There was a problem opening: $!" +; my @primers = <$data>; close $data; chomp @primers; use Algorithm::Combinatorics qw(combinations); my $strings = \@primers; my $iter = combinations($strings, 2); open(my $fh, '>', $outfile); while (my $c = $iter->next) { print $fh @$c, "\n"; } print ("Finished. The results are located at $outfile\n\n");

I was wondering if there was a simple method for allowing outfile to be sequentially numbered if an existing file is found i.e. Results.txt, Results1.txt, Results2.txt? I've seen a few methods around however they do seem quite long and i'm curious to see if there's an available module or easier way to do it! Thanks!

  • Comment on Sequentially numbering output files rather than overwriting an existing file
  • Download Code

Replies are listed 'Best First'.
Re: Sequentially numbering output files rather than overwriting an existing file
by kcott (Archbishop) on Jan 08, 2014 at 15:34 UTC

    G'day TJCooper,

    Here's one way you might go about this:

    #!/usr/bin/env perl -l use strict; use warnings; use autodie; my $highest = 0; my $re = qr{pm_1069813_results(\d+)\.txt}; opendir my $dh, '.'; map { /$re/ and $1 > $highest and $highest = $1 } readdir $dh; closedir $dh; my $next_file = 'pm_1069813_results' . ++$highest . '.txt'; print "Next file: $next_file";

    Output:

    Next file: pm_1069813_results4.txt

    Current files:

    $ ls -1 pm_1069813_results*.txt pm_1069813_results1.txt pm_1069813_results2.txt pm_1069813_results3.txt

    -- Ken

      Interesting way of going about it. Thank you!
Re: Sequentially numbering output files rather than overwriting an existing file
by educated_foo (Vicar) on Jan 08, 2014 at 17:05 UTC
    For the first unused "$name$n.txt" file:
    if (-f "$name.txt") { $n=1; $n++ while -f "$name$n.txt"; }
    For one greater than the highest "$name$n.txt" file, something like kcott's solution below works.
      For more visually pleasing output:
      if (-f "$name.txt") { $n=1; my $fn = sprintf "%s-%05d\.txt", $name, $n; $n++ while -f $fn; }
Re: Sequentially numbering output files rather than overwriting an existing file
by duelafn (Parson) on Jan 09, 2014 at 00:46 UTC

    If you don't want to risk races, use sysopen and loop until you can create the file yourself:

    #!/usr/bin/perl -w use strict; use warnings; use 5.010; use Fcntl qw/ O_CREAT O_EXCL O_WRONLY /; my $fh = open_next( "Results", ".txt" ); print $fh "Hello!\n"; sub open_next { my ($prefix, $suffix) = @_; my $number = 0; my $FH; until (sysopen($FH, ($prefix . ($number || "") .$suffix), O_WRONLY +|O_EXCL|O_CREAT)) { $number++; } return $FH; }

    Good Day,
        Dean

Re: Sequentially numbering output files rather than overwriting an existing file
by Laurent_R (Canon) on Jan 08, 2014 at 23:27 UTC

    You can work on VMS: the OS automatically assigns version numbers (starting with 1) to files that you create. If you create a "foo.txt" file, VMS actually creates "foo.txt;1". When you modify this file, a new version, "foo.txt;2" will be created. ;-)

    More seriously, I had to create recently directories with sequence numbers, say something like foo1, foo2, foo3, etc. I did something similar to this (from sheer memory, I did not test the version posted here):

    my $root_name = "foo"; my $next_number = (sort {$b <=> $a} map {/(\d+)$/; $1} glob("${root_na +me}*"))[0] + 1; my $next_name = "$root_name$next_number"; # ...
    Perhaps slightly less efficient than Ken's code if you have hundreds of thousands of directory entries (because a full sort if overkill in this context), but my sequence numbers had to be limited by a smaller upper limit anyway, but using sort made the coding easier.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2024-04-23 06:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found