Reputation: 6744
The following opens STDIN
and then echos user input:
open my $in, '-';
print "You said: $_" while(<$in>);
However, the following snippet dies because it can't find any file called '-':
open my $in, '<', '-'; # dies
print "You said: $_" while(<$in>);
Why does the two-argument open
work for this but the three-argument open
dies? I was hoping for a simple method of opening either a file or STDIN based on user input, and I don't want to use 2-argument open.
Upvotes: 4
Views: 386
Reputation: 386501
Three-arg open fails because there's no file named -
. That's the whole point of three-arg open. Gotta have a way of opening files without the file names being treated as code!
This should do the trick:
open(STDIN, '<', $qfn)
if $qfn;
Technically, there is a way of opening STDIN with three-args open
.
# Creates a new system handle (file descriptor).
open(my $fh, '<&', fileno(STDIN));
open(my $fh, '<&', \*STDIN);
open(my $fh, '<', "/proc/$$/fd/".fileno(STDIN)); # Linux
# Creates a new Perl handle for the existing system handle
open(my $fh, '<&=', fileno(STDIN));
open(my $fh, '<&=', \*STDIN);
Upvotes: 2
Reputation: 50667
As already mentioned, you can use STDIN
instead of opening it explicitly,
use autodie;
my $in;
$in = ($file eq "-") ? \*STDIN : open($in, "<", $file) && $in;
Upvotes: 2
Reputation: 118156
In the two-argument (and one-argument) form, opening
<-
or-
opensSTDIN
and opening>-
opensSTDOUT
.
I think this makes it clear that the special treatment of -
is specific to the one- or two-argument forms.
You could just assign \*STDIN
to your $in
, or open a file based on user input.
Upvotes: 2