Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

STDIN following on?

by tfrayner (Curate)
on Aug 10, 2001 at 22:49 UTC ( [id://103996]=perlquestion: print w/replies, xml ) Need Help??

tfrayner has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm trying to get a script to read a list of files from the command line or accept a list from STDIN (e.g. ls -1 | script.pl):

if (@ARGV){ foreach my $path(@ARGV){ $path=File::Spec->rel2abs($path); } $passhash{filearrayref}=\@ARGV; } elsif ($passhash{stdin}){ # flag to indicate input from stdin my $i=0; foreach my $path(<>){ chomp($path); $path=File::Spec->rel2abs($path); $passhash{filearrayref}[$i]=$path; $i++; } } else {die ("No input files specified.\a\n");}

The script subsequently asks for further input from STDIN (in a separate, unrelated subroutine):

print STDERR ("Directory \'$$pref{changedir}\' aleady exists. Overwrit +e?\n". "[Y(es)/N(o)/R(eselect destination)/C(lobber all duplicates)]". "\a\n"); my $answer = <STDIN>; chomp ($answer); # line 106 (see below) print "$answer\n"; # for testing purposes
The problem is that the second input gets ignored. The script doesn't wait for user input at all. In fact it behaves as though the variable $answer is never initialised. I'm using strict and warnings, and it tells me:
Use of uninitialized value in scalar chomp at script.pl line 106.

This problem doesn't occur if the flag variable $passhash{stdin} is not set. It looks suspiciously like the problem Sojourner described here, but the solution in that case (use CGI.pm) doesn't seem to apply here (this thing's going nowhere near a web site).

I'm sure I'm missing something simple here, but I can't for the life of me figure out what it is. Any help would be greatly appreciated.

Thanks.

Replies are listed 'Best First'.
Re: STDIN following on?
by CheeseLord (Deacon) on Aug 10, 2001 at 22:54 UTC

    As I understand it, your first input call (w/ <>) is slurping up ALL your data, so that the next read (using <STDIN>) is reading nothing - that's because the first diamond is in list context, so everything gets read until EOF.

    Once again, that's just my opinion. I could easily be misunderstanding your problem, but I hope that helps somewhat.

    Somewhat unrelated note/Update: It's been said a few times around here that <> isn't a good idea for reading from STDIN unless you're sure you just want the unadorned diamond (which will read in from the files listed in @ARGV and not STDIN). If that's not the case for you (I can't tell from your code), then I'd suggest switching the call, for both clarity and safety.

    His Royal Cheeziness

      Hmmm...
      The first read of STDIN was supposed to slurp up all the data, and if the second read doesn't occur the script works fine and behaves as it should. The idea was that I then add a new line to STDIN typing on the console for the second read. I wonder if the second read is going back to the beginning of the original input and processing it again? I don't know how this explains the way that $answer appears to be decidedly undef, though...

      Update: :-) Unfortunately, I've tried both <> and <STDIN>, and both give the same result.

        Well, try this little test:

        eoftest.pl:
        #!/usr/bin/perl -w use strict; my @lines = <STDIN>; my $line = <STDIN>; print @lines; print "----\n"; print $line;

        Typing in the input from the terminal works great. But here's the problem:

        cat file | eoftest.pl

        You'll get your uninitialized value warning there. Reason? I think it has to do with the redirection (or to be more correct, piping) of STDIN when running your script. STDIN is now a pipe from "cat file" and can't have anything more read from it - causing the warning.

        Update: You may want to do something like this:
        open STDIN, "/dev/pts/0";
        to reopen STDIN to the correct place.

        His Royal Cheeziness

Re: STDIN following on?
by tfrayner (Curate) on Aug 11, 2001 at 20:18 UTC
    Okay, I think CheeseLord has it cracked. As he suggests, closing the STDIN filehandle and reopening it on the /dev/tty (or /dev/pts/xx or whatever) device from which the script was called works a treat. Thanks very much!

    (Update): i.e.

    use POSIX; close(STDIN); my $tty=POSIX::ctermid(); open(STDIN,"$tty");

    Thanks very much!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://103996]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2024-04-25 20:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found