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

Dear Wise Monks, I'm trying to open a bunch of files in ARGV and read them line by line and then split in the way I'm specifying in the code - and then for testing I am trying to print their contents. However I'm getting a "Can't open GLOB(0x605d48): No such file or directory" error :( Can anyone please give me a hint what's happening? I'd be extremely grateful.

I'm trying to use two different filehandles to open the files and then push those two filehandles into @ARGV. Then I'm trying to use the <> operator. There is something that messes things up though and I'm getting an error. Any hints/feedback would be immensely useful.
#!/bin/perl/ use strict; use warnings; my $molec1 = "molec1"; my $molec2 = "molec2"; my $input1; my $input2; @ARGV = (); my $i; my $j; my $path = "/store/group/comparisons"; my $line; my @columns; my $nextUnless = 2; # nr of lines to skip from beginning my $CountLines = 0; # total nr of lines in all files, including commen +ts for ($i=1; $i<=3; $i++) { open $input1, '<', "$path\/File-${molec1}-cluster${i}.out" or die $! +; for ($j=1; $j<=4; $j++) { open $input2, '<', "$path\/File-${molec2}-cluster${j}.out" or die +$!; push @ARGV, $input1; push @ARGV, $input2; my @list; my $list; my $a; my $b; while ($line = <>) { $CountLines += 1; next unless $. > $nextUnless; chomp $line; $line =~ s/^\s+|\s+$//g; push @list, [split/\s+/, $line]; @columns = split /\s+/, $line; } close $input1; close $input2; for ($a=0; $a<=$#columns; $a++) { for ($b=0; $b<=$#columns; $b++) { print "$list[$a][$b] "; # to check matrices } print " \n"; } } # for j } # for i

Replies are listed 'Best First'.
Re: trying to read files in @ARGV but getting GLOB error! :(
by choroba (Cardinal) on Jun 25, 2017 at 19:02 UTC
    The diamond operator <> reads from the files specified in @ARGV , not from filehandles in @ARGV . Don't push filehandles to @ARGV , push the file names instead.

    BTW, you can push more than one thing at a time:

    push @ARGV, "$path/File-$molec1-cluster$i.out", "$path/File-$molec2-cl +uster$j.out";

    Are you sure you want to push the $i-file repeatedly?

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Is writing data to @ARGV considered good form?

        I agree with choroba, and just wanted to add that additionally I might consider it acceptable in a longer script to use local @ARGV in a small scope (keeping in mind that this is dynamic scoping, so any function called from within that block will also see the localized values). One neat trick is to combine this with with $^I to do inplace editing of files, like with the -i switch:

        $ perl -i -ple '$_.="\n" if $. % 4 == 0; close ARGV if eof' -- FILES

        Becomes:

        { # new scope for local local *ARGV; @ARGV = @files; local $^I = ""; # -i command line switch while (<>) { print $_; print "\n" if $. % 4 == 0; close ARGV if eof; } }

        (From here.)

        Update: Fixed this potential issue in the above example code.

        I wouldn't object to it in a short script. In a large program or application, it's changing the global state, so definitely a don't.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        yes, why not?

        @ARGV is something perl make at disposal for you: if you know what are you doing you can modify at your will: inserting or shifting from it.

        Rare items Perl gives you are bad to modify: some of the puncuation variables are a good example to be bad to modify. What the need to modify $. current line number for example? Or what you gain setting $^O the operating system label?

        @ARGV and many other varibles you have at disposal are useful to modify. Getopt::Long make a lot of work on @ARGV even if principally shifting it.

        But consider you want to write a simple program, possibly a oneliner, that glob files and unfortunately you are working in a user unfriendly OS that does not glob files on command line. You can use glob expanding @ARGV in a BEGIN block:

        perl -lne "BEGIN { @ARGV =  map glob, @ARGV; print qq(considering ).scalar @ARGV.qq( files\n);} ....

        Or you want to have the first file processed to be the comparing stone and the following ones searched just for lines present in the first one:

        perl -lne "%ln;BEGIN{open $f,shift;map{chomp;$ln{$_}++}<$f>}print qq($ +ARGV line\t$.\t[$_]) if exists $ln{$_};close ARGV if eof" dog.txt cat.txt other.txt

        Or, if you have enough hubrys, want to evaluate some line number range popped from @ARGV while printing just some line of a file:

        perl -E    "say+(0,<>)[eval pop]"                          linenumber.txt 1,3..5

        So, imho, modify @ARGV if you need to!

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      Oh! Good to know, thanks so much. That'll be so useful for the future. And no, you're right, I don't want to push the $i-file repeatedly, that was a mistake.

      Thank you so much!

      There is something strange happening though, I think it's because there is something wrong in this bit

      for ($i=1; $i<=3; $i++) { open $input1, '<', "$path\/File-$molec1-cluster$i.out" or die $!; push @ARGV, "$path\/File-$molec1-cluster$i.out"; for ($j=2; $j<=3; $j++) { open $input2, '<', "$path\/File-$molec2-cluster$j.out" or die $!; push @ARGV, "$path\/File-$molec2-cluster$j.out";

      When I print the contents of the files, the result is completely chaotic. I would expect the printing to be sequential like so

      1st print file molec1-$i=1

      2nd print file molec1-$i=2

      3rd print file molec1-$i=3

      4th print file molec2-$j=2

      5th print file molec2-$j=3

      but in my case the end result is a combination of $i-file with only the second option of $j-file repeated ($j=3), while the $j=2 is completely ignored.

      What i'm getting is:

      1st print file molec1-$i=1

      2nd print file molec2-$j=3

      3rd print file molec1-$i=2

      4th print file molec2-$j=3 (repeat)

      5th print file molec1-$i=3

      6th print file molec2-$j=3 (repeat)

      I don't understand why this pattern appears...?
        for ($i=1; $i<=3; $i++) { open $input1, '<', "$path\/File-$molec1-cluster$i.out" or die $!; push @ARGV, "$path\/File-$molec1-cluster$i.out"; for ($j=2; $j<=3; $j++) { open $input2, '<', "$path\/File-$molec2-cluster$j.out" or die $!; push @ARGV, "$path\/File-$molec2-cluster$j.out";

        I don't understand why this pattern appears...?

        Hi, it does look odd. The only thing I see is missing } sub-ending brackets in your code, maybe that missing sub closure is important. As always, a small-self-contained working example would be useful here. Because usually, when you need to make an example, you see the error yourself.


        I'm not really a human, but I play one on earth. ..... an animated JAPH
Re: trying to read files in @ARGV but getting GLOB error! :(
by karlgoethebier (Abbot) on Jun 26, 2017 at 13:50 UTC
    "...open a bunch of files in ARGV and read them line by line ...split... two different filehandles..."

    May be that i miss totally the point, but why don't you simply use Getopt::Long and then open the files and iterate over them the usual way?

    See also Re: GetOpt Organization.

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help