Nate Glenn
Nate Glenn

Reputation: 6744

2- vs 3-argument open with '-'

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

Answers (3)

ikegami
ikegami

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

mpapec
mpapec

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

Sinan &#220;n&#252;r
Sinan &#220;n&#252;r

Reputation: 118156

perldoc -f open:

In the two-argument (and one-argument) form, opening <- or - opens STDIN and opening >- opens STDOUT.

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

Related Questions