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

I have 30 files called graph_set_1.out --> graph_set_30.out
How would I modify the following code so to open each one consecutively.
I don't neccessarily have to have 30 files, so the I need to be general.
I have tried adding a counter but with no luck ? e.g. (graph_set_$i.out)
#!/usr/local/bin/perl $in_filename = "graph_set_1.out"; open (IN,"$in_filename") or die "Can't open $in_filename:$!\n";
cheers harry

Replies are listed 'Best First'.
Re: opening consecutive files
by Abigail-II (Bishop) on Jun 27, 2003 at 13:08 UTC
    You don't show us the code with the counter, so it's hard to say where you went wrong. Here's a loop that starts with opening graph_set_1.out, and continues to increase the number until there's no matching file.
    for (my $c = 1;; $c ++) { my $file = "graph_set_$c.out"; last unless -f $file; open my $fh => "<", $file or die "Failed to open $file: $!"; ... # Do something with $fh. }

    Abigail

      I have added the code that you have supplied.
      what I want to do is match the specified strings from each graph_set.out file and print strings into .txt file.
      It's not printing anything into the .txt file ? ?
      #!/usr/local/bin/perl for (my $c = 1;; $c ++) { my $file = "graph_set_$c.out"; last unless -f $file; open my $fh => "<", $file or die "Failed to open $file: $!"; local $/ = undef; # undef record seperator my $string = <IN>; # read whole file into string close (IN); my @gset_match = ($string =~ /([A-Z]\s\d+,\s\d+\(\s*\d+\))/g); open (TEXT, ">graph_set.txt") or die "Can't create graph_set.txt: $!\n +"; foreach $_(@gset_match) { print TEXT "$_\n"; } close TEXT; }
        You are reading from a handle named IN, while the open opens a handle $fh. That isn't going to work. If you turn warnings on (which usually is a good idea), Perl would have told you that you were reading from an unopened filehandle.

        Abigail

Re: opening consecutive files
by dragonchild (Archbishop) on Jun 27, 2003 at 12:58 UTC
    use strict; use warnings; use IO::File; foreach my $i (1 .. 30) { my $fh = IO::File->new("graph_set_$i.out") || die "Cannot open $i'th file\n"; # Use $fh here $fh->close; }

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: opening consecutive files
by Zaxo (Archbishop) on Jun 27, 2003 at 13:23 UTC

    There are two steps to this. First you need to get a list of file names and sort them in the desired order. Then, open the files in a for loop over the sorted list.

    my $path = '/path/to/dir'; my @names = glob $path . '/graph_set_*.out'; # @names is in alpha order, so sort numerically my @sorted_names = sort { my ($x, $y); $a =~ /graph_set_(\d+)\.out$/ and $x = $1; $b =~ /graph_set_(\d+)\.out$/ and $y = $1; $x <=> $y } @names; # That may benefit from a Schwartzian Transform # Now, do the loop for (@sorted_names) { open local(*IN), "< $_" or die $!; # ... close IN or die $!; }
    If you can write for recent enough perl, three-arg open and lexical filehandles ('open my $fh, '<', $_ or die $!;') would be good. If you want all the handles open at the same time, push $fh onto an array or assign array elements to it.

    After Compline,
    Zaxo

Re: opening consecutive files
by BrowserUk (Patriarch) on Jun 27, 2003 at 13:34 UTC

    Rather than trying to open 30 files when some or all of them may not exist, and dieing if one of them doesn't (unless that makes sense). You could let perl tell you which files exist and just open those that do.

    while( my $file = <graph_set_*.out> ) { next unless $file =~ m[graph_set_[123]?[0-9].out]; open IN, '<', $file or warn "Couldn't open file $file because $!"; #Do stuff close IN; }

    The caveat is that you may not get the files in the order you want them if that is important. They will be in sorted order (as of 5.8 I think) but as your numbers don't appear to have leading zeros, they will come in ascii order 1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 26 27 28 29 3 30 4 5 6 7 8 9

    If that's a problem, then you could do

    for $file (sort{ $a=~/(\d+)/ <=> $b=~/(\d+)/ } <graph_set_*.out> ) { open... .... close... }

    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


      there is nothing printing into the txt file.
      is there anything obviously wrong ?
      I know the pattern matching code is right.
      #!/usr/local/bin/perl while( my $file = <graph_set_*.out> ) { next unless $file =~ m[graph_set_[123]?[0-9].out]; open IN, '<', $file or warn "Couldn't open file $file because $!"; local $/ = undef; # undef record seperator my $string = <IN>; # read whole file into string close IN; } my @gset_match = ($string =~ /([A-Z]\s\d+,\s\d+\(\s*\d+\))/g); open (TEXT, ">graph_set.txt") or die "Can't create graph_set.txt: $!\n +"; foreach $_(@gset_match) { print TEXT "$_\n"; } close TEXT;
        Had you turned on strict, Perl would have told you that where you match $string that variable is out of scope. What you do is, in a loop, read in each file, store the context in a lexical variable (which is gone at the next iteration of the loop). Then, outside the loop, after discarding the content of all the files, you do the matching.

        But there's nothing to match against.

        Abigail

Re: opening consecutive files
by bobn (Chaplain) on Jun 27, 2003 at 13:15 UTC
    #!/usr/local/bin/perl # NOT TESTED @files = map {$_->[1]} sort {$a->[0] <=> $b->[0] } map { /^graph_set_([[0-9]+).out$/; [ $1, $_ ] } grep { /^graph_set_[0-9]+.out$/ } glob('graph_set_*'); # lookup schwartzian transform, then read the preceding from the botto +m up for (@files) { open(F, $mode, $_); # do whatever close F; }


    --Bob Niederman, http://bob-n.com