Jason Wozniak wrote:
>>
>> I am trying to put together a search and replace program that I can
>> string together with typical unix shell commands like find, and
>> grep.  However, I can't get past the initial read of the files I
>> want to process, using the diamond operator.  I lose the first
>> argument in the list every time.  I put the below code together for
>> debugging purposes to figure out what's going on.
>>
>> while (<>) {
>>         @files = <STDIN>;
>> }
>> $count = scalar @files;
>> print "There are $count files in the process list!\n";
>> print @files;
>>
>>
>> When I run this with the command:  find /u06 -name glog.log.bak* |
>> /export/home/jwozniak/fm.pl
>> It drops the first file in the list for output.
>>
[snip demonstration]
>>
>> What am I missing?

You've written:

    do {@files = <STDIN>} while <>;

which looks like you're expecting <> to be some indicator
of whether STDIN is empty or not. In fact it's a lot more
complicated and magical than that. <> reads lines from all
of the files specified on the perl command line and executes
the body of the loop with $_ set to each line. If there
were no command-line arguments (as in your case) it will
try to read lines from STDIN.

What's happening then is that the <> executes, finds no
parameters, and so reads the first line from STDIN and
puts it into $_ for you. This is successful, so the body
of the loop executes, putting all of the remaining lines
into @files and ignoring $_. <> then executes again and
finds it is at end of file for STDIN and so the loop
exits.

>
> Well as a followup to my own email..
>
> This works where the while loop does not, so at least now I've found
> a way to pipe the output of the unix find command into my program :)
> I'm still not sure I understand why though...
>
> chomp(@files = <>);

Yes, but you're still using the 'magic' <> operator when
you're not really concerned with command line parameters
at all. More directly this should be written:

    chomp (@files = <STDIN>);

> I had also tried:
>
> while (<>) {
> @files = $_;
> }
>
> but that had the same problem, so somehow the while loop causes the
> first argument to be dropped from the input stream?

No. This will leave your array containing just the last of the
filenames. As in the first case, <> redirects its input to STDIN
because there are no command-line parameters. It then reads one
line at a time from STDIN, assigning to @files the one-element
list of just that filename. Each line read will replace the
previous one in @files, leaving just the last record.

This would work:

    while (<>) {
        push @files, $_;
    }

because it adds the record to the end of the array each time.

I'm not too hot on Unix, but I think your find command is
searching directory '/u06' for files matching 'glog.log.bak*'?
This can be done directly in Perl, avoiding all that ugly
piping.

    my @files = glob('/u06/glog.log.bak*');

which may be subtly different from what you have done, but
I'm sure someone will let me know!

Hope this helps.

Rob




-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to