biren.K
biren.K

Reputation: 247

Perl mis-behaves when a file is given as an argument

Hi below is my perl code :

#!/usr/bin/perl -w

no warnings;
use Env;

my $p4user = $ENV{'P4USER'};
my $current_path = $ENV{'PWD'};
print("\t Hello $p4user. You are currently in $current_path path.\n");

open($user_in,"$ARGV[0]") || die("failed to open the argument file $ARGV[0]\n");

print("\t To create a new client enter '1' |");
print("\t To use an existing client enter '2' : ... ");

my $cl_op = <>;
chop($cl_op);

if (($cl_op == 1) || ($cl_op == 2))
{
  # do something common for both condition

  if ($cl_op == 1)
  {
    # do something
  }
  elsif ($cl_op == 2)
  {
  # do something
}
}
else
{
  die("\n\t Sorry. Invalid option : $cl_op\n");
}

Then the script runs like :

     Hello biren. You are currently in /remote/vgvips18/biren/tcf_4nov path.

     Sorry. Invalid option : ###################################################################
     To create a new client enter '1' |      To use an existing client enter '2' : ... 

Any Idea why the script is behaving like this. When I comment out this line "

open($user_in,"$ARGV[0]") || die("failed to open the argument file $ARGV[0]\n");

", the script runs fine. Can anyone help why the script behaves when i pass a file as an argument on command line.

Upvotes: 0

Views: 368

Answers (3)

mob
mob

Reputation: 118685

<> is shorthand for <ARGV>, where ARGV is a special (i.e., magic) filehandle that can either mean filenames from your command-line arguments, or STDIN if there are no command-line arguments. Perl will make the decision how to treat ARGV based on the contents of @ARGV the first time it is used.

If you want invocations of your program like

perl my_script.pl userfile inputfile
perl my_script.pl userfile < inputfile
cat inputfile | perl my_script.pl userfile

to all work alike, you will want to consume the first element of @ARGV before you refer to ARGV. Like so:

my $userfile = shift @ARGV;   # removes $ARGV[0] from front of @ARGV
open $user_in, '<', $userfile or ...
...
my $cl_op = <>;

Now $cl_op is being read from the second filename you provide, or from STDIN.

Upvotes: 0

Ron Bergin
Ron Bergin

Reputation: 1068

my $cl_op = <>;

That will read the first line of the file you passed as the arg.

To make it read the user response to your prompt, change it to this:

my $cl_op = <STDIN>;

Upvotes: 2

Ben Grimm
Ben Grimm

Reputation: 4371

It's wise to include sanity checks to verify that a file name was passed as an argument before attempting to open it.

my $user_in;
if ( defined $ARGV[0] ) { 
   die "$ARGV[0] does not exist.\n" unless -e $ARGV[0];
   open($user_in,"$ARGV[0]") 
      or die("failed to open the argument file $ARGV[0]: $!\n");
}

Upvotes: 1

Related Questions