Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: How to get filename when using <> construct?

Tags:

perl

Perl offers this very nice feature:

while ( <> )
{
    # do something
}

...which allows the script to be used as script.pl <filename> as well as cat <filename> | script.pl.

Now, is there a way to determine if the script has been called in the former way, and if yes, what the filename was?

I know I knew this once, and I know I even used the construct, but I cannot remember where / how. And it proved very hard to search the 'net for this ("perl stdin filename"? No...).

Help, please?

like image 285
DevSolar Avatar asked Jun 21 '12 16:06

DevSolar


People also ask

How do I get the filename from the path in Perl?

use File::Basename; ... $file = basename($path); Why did $file=$path=~s/.

What is the extension of Perl script?

There are many programs designed for programmers available for download on the web. As a Perl convention, a Perl file must be saved with a . pl or.PL file extension in order to be recognized as a functioning Perl script.


2 Answers

The variable $ARGV holds the current file being processed.

$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3
like image 167
Igor Chubin Avatar answered Oct 01 '22 05:10

Igor Chubin


The I/O Operators section of perlop is very informative about this.

Essentially, the first time <> is executed, - is added to @ARGV if it started out empty. Opening - has the effect of cloning the STDIN file handle, and the variable $ARGV is set to the current element of @ARGV as it is processed.

Here's the full clip.

The null filehandle "<>" is special: it can be used to emulate the behavior of sed and awk, and any other Unix filter program that takes a list of filenames, doing the same to each line of input from all of them. Input from "<>" comes either from standard input, or from each file listed on the command line. Here's how it works: the first time "<>" is evaluated, the @ARGV array is checked, and if it is empty, $ARGV[0] is set to "-", which when opened gives you standard input. The @ARGV array is then processed as a list of filenames. The loop

   while (<>) {
       ...                     # code for each line
   }

is equivalent to the following Perl-like pseudo code:

   unshift(@ARGV, '-') unless @ARGV;
   while ($ARGV = shift) {
       open(ARGV, $ARGV);
       while (<ARGV>) {
           ...         # code for each line
       }
   }

except that it isn't so cumbersome to say, and will actually work. It really does shift the @ARGV array and put the current filename into the $ARGV variable. It also uses filehandle ARGV internally. "<>" is just a synonym for "<ARGV>", which is magical. (The pseudo code above doesn't work because it treats "<ARGV>" as non-magical.)

like image 24
Borodin Avatar answered Oct 01 '22 04:10

Borodin