Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

How do I read the files in @ARGV one by one

by Elias (Pilgrim)
on Mar 19, 2001 at 20:49 UTC ( #65453=perlquestion: print w/replies, xml ) Need Help??
Elias has asked for the wisdom of the Perl Monks concerning the following question:

Of each dropped file, I would like to pass the filename first, and then the data, to an array. I have tried this:

foreach my $file (@ARGV) {
        push @data, substr($file, -12, 12);
        while (<>) {
                push (@data=>$_);

However, it does not work: Only the first filename is pushed onto the array, followed by all the data in the files. Should I make a filehandle for each $file in @ARGV and loop the while statement over these filehandles? Is there another, more elegant solution?

  • Comment on How do I read the files in @ARGV one by one

Replies are listed 'Best First'.
Re (tilly) 1: How do I read the files in @ARGV one by one
by tilly (Archbishop) on Mar 19, 2001 at 21:30 UTC
    How do you distinguish filenames from contents of files in your data structure? A hash of arrays is cleaner.

    The following snippet should work:

    $data{$_} = [] foreach @ARGV; while (<>) { push @{$data{$ARGV}}, $_; }
    The purpose of the first line is to make sure that files which are empty are included in your hash.
Re: How do I read the files in @ARGV one by one
by merlyn (Sage) on Mar 19, 2001 at 21:48 UTC
    @ARGV = $_, push @data, $_, <> for @{[@ARGV]};
    Hmm. There was some other clever trick to dup a list too, but I can't recall now.

    -- Randal L. Schwartz, Perl hacker

    update: Yeah, it's
    @ARGV = $_, push @data, $_, <> for map $_, @ARGV;
Re: How do I read the files in @ARGV one by one
by Masem (Monsignor) on Mar 19, 2001 at 20:54 UTC
    Right now, you have no file handles to those data files to speak of, so it's odd how you are getting even that data. The way you want to do it is:
    foreach my $file (@ARGV) { if ( -e $file ) { # double check existence push @data, $file; open FILE , '<'.$file or die $!; while( <FILE> ) { push @data, $_; } close FILE; } }

    Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
      It's not odd because he's using the <> operator, which returns all the data from all the files listed in @ARGV, all in one pass, line by line. It doesn't let you break it up by file, though.

(jeffa) Re: How do I read the files in @ARGV one by one
by jeffa (Bishop) on Mar 19, 2001 at 20:58 UTC
    Personally, I prefer to just open a filehandle:
    use IO::File; my %files; foreach my $name (@ARGV) { my $file = IO::File->new($name) or next; # print error message her +e, etc. my @lines = <$file>; $files{$name} = \@lines; $file->close; }


Re: How do I read the files in @ARGV one by one
by bjelli (Pilgrim) on Mar 19, 2001 at 21:39 UTC

    The trouble with your code is that <> does advanced magic: it reads in all the files on the command line line by line. You can find out which file you are reading right now by looking at $ARGV.

    So for your little problem, you could remember what $ARGV was when you last read a line and check if $ARGV has changed:

    my $OLDARGV; while (<>) { push(@data, $ARGV) if $ARGV ne $OLDARGV; push(@data, $_); $OLDARGV=$ARGV; }

    But I admit that Masems code is probably easier to figure out.

    Brigitte    'I never met a chocolate I didnt like'    Jellinek
Re: How do I read the files in @ARGV one by one
by merlyn (Sage) on Mar 19, 2001 at 23:59 UTC

      Make sure you don't do what I just did:

      my @ARGV = $file;

      The my creates a new, local @ARGV which is not what you want. Doh!

Re: How do I read the files in @ARGV one by one
by busunsl (Vicar) on Mar 19, 2001 at 20:55 UTC
    Have a look at 'eof', it will tell you when a file ends.

    perldoc -f eof

      I'd like to encourage you to check out the above advice.

      Here is an alternative that I am becoming fond of:

      my @data; foreach my $file (@ARGV) { push @data, substr( $file, -12, 12 ); local( *ARGV ); @ARGV= ($file); push( @data, <> ); }

              - tye (but my friends call me "Tye")
Re: How do I read the files in @ARGV one by one
by orbital (Scribe) on Mar 19, 2001 at 21:23 UTC
    You can also check into Getopt::Std or Getopt::Long, both of these modules give you more control over the command line. here is an example usage:
    use Getopt::Long; Configure( \%Config ); if( $Config{help} ){ Syntax(); exit();} ....Code Goes Here..... sub Configure { my( $Config ) = @_; my $Result = 0; Getopt::Long::Configure( "prefix_pattern=(-|\/)" ); $Result = GetOptions( $Config, qw( del|d=i length|l=i path|p=s first|f=s reports|r=i help|?|h ) ); if (! scalar $Config->{line}) { $Config->{line}=132;} if (! scalar $Config->{reports}) { $Config->{reports}=1;} if (! exists $Config->{path}) { Syntax(); exit; } if (! exists $Config->{first}) { Syntax(); exit; } if (exists $Config->{del}) { Delete(); } $stream = $Config->{line}; $rptpag = $Config->{reports}; $dir = $Config->{path}; $firstln = $Config->{first}; } sub Syntax { print <<EOT; ------- Used for Adding/Removing ANSI printer control characters. Syntax: [-l length] [-p path] [-f first] [-r reports] [-d del] -l..........Defines length of each line in the files. [default +=132] -p..........Specifies the directory path to process. [must be +defined] (Directory must end with a \\) -f..........Defines the first line of a report. [must be defin +ed] -r..........Set the number of reports per page. [default=1] -d..........Deletes defined number of characters from beginnin +g of each line. [optional] -h..........This help screen. *(looks for all *.dat in specified directory, saves original t +o *.bak) EOT }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://65453]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (4)
As of 2017-06-26 07:18 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (572 votes). Check out past polls.