Markus Dehmann said:
I have a convenient way to open possibly gzip'ed fil
open(F, ($f =~ m/\.gz$/) ? "gunzip -c $f |" : "$f");
[gzip -d reads .txt, .gz, .Z files]
... the "universal input pipe",
$gzip_pid = open( FH, $fp="/usr/local/bin/gzip -dfc $infile |" )
Markus Dehmann said:
Now, a slightly offtopic question:
Why do people often use the full path to an application (like here,
/usr/local/bin/gzip)? That just makes it more unlikely to work, since
my gzip might be in /usr/bin.
Why not just: open(F, "gzip -dfc $infile |");
#!perl -w
as the first line of a perl program, and let the $PATH variable figure
out which perl is meant?
I do it, because I write scripts for a audience that may have a
variety of PATH based on their group/culture/history,
and "I think I know better than they do" what path I want to use;
ie the one that works for me.
Plus I might have read a security warning somewhere that said
a full path is better, because it doesn't call the shell interpreter?
But that doesn't appear to be the case nowdays. (perl 5.8.0)
Diverging back to a related subject, I tried updating this to
PBP recommendations, but am puzzled by some of the results.
#!/usr/local/bin/perl
use strict;
use warnings;
## version 0
my ($pid0,$file0,$fp0,$infile0);
$infile0 = "x;touch y0;echo 'twerp'";
$pid0 = open( FH, $fp0 = "/usr/local/bin/gzip -dfc $infile0 |" ) || die "oops '$fp0' :$!\n";
print "v0
id0='$pid0', fp0='$fp0', infile0 = '$infile0', \nlines = >>",<FH>,"<<\n";
close (FH) || warn "close error on '$fp0' : $!\n";
# results : also creates file 'y0' due to shell processing
#v0
id0='6900', fp0='/usr/local/bin/gzip -dfc x;touch y0;echo 'twerp' |', infile0 = 'x;touch y0;echo 'twerp'',
#lines = >>this is line 1 of file x
#twerp
#<<
# version 1
my $infile1 = "x;touch y1;echo 'twerp'";
my $fp1; # why cant my $fp1 be used in next line?
my $pid1 = open( my $file1, "-|", $fp1 = "/usr/local/bin/gzip -dfc $infile1" ) || die "oops '$fp1' :$!\n";
print "v1
id='$pid1', file1='$file1', fp1='$fp1', infile1 = '$infile1', \nline1 = >>",<$file1>,"<<\n";
close ($file1) || warn "close error on '$fp1' : $!\n";
# Results : lexical filehandle and variables; still creates 'y1' due to shell processing
#v1
id='6903', file1='GLOB(0x804ccb0)', fp1='/usr/local/bin/gzip -dfc x;touch y1;echo 'twerp'', infile1 = 'x;touch y1;echo 'twerp'',
#line1 = >>this is line 1 of file x
#twerp
#<<
# version2
my $infile2 = "x;touch y2;echo 'twerp'";
my $fp2; # perl v3 p751 "pipe from bare command
my $pid2 = open( my $file2, "-|", $fp2 = 'gzip', '-dfc', $infile2 ) || die "oops '$fp2' :$!\n";
print "v2
id2='$pid2', file2='$file2', fp2='$fp2', infile2 = '$infile2', \nline2 = >>",<$file2>,"<<\n";
close ($file2) || warn "close error on '$fp2' : $!\n";
# Results: bareword commands, no shell processing, no touch on file 'y2', no error since file exists
#v2
id2='6906', file2='GLOB(0x8062d94)', fp2='gzip', infile2 = 'x;touch y2;echo 'twerp'',
#line2 = >>this is only line of file "x;touch y2;echo 'twerp'"
#<<
# version3
my $infile3 = "x;touch y3;echo 'twerp'";
my $fp3; # perl v3 p751 "pipe from bare command
my $pid3 = open( my $file3, "-|", $fp3 = 'gzip', '-dfc', $infile3 ) || die "oops '$fp3' :$!\n";
print "v3
id3='$pid3', file3='$file3', fp3='$fp3', infile3 = '$infile3', \nline3 = >>",<$file3>,"<<\n";
close ($file3) || warn "close error on '$fp3' : $!\n";
# Results : no shell processing, shell error on gzip since no such file
#gzip: x;touch y3;echo 'twerp'.gz: No such file or directory
#v3
id3='6907', file3='GLOB(0x80954ec)', fp3='gzip', infile3 = 'x;touch y3;echo 'twerp'',
#line3 = >><<
#close error on 'gzip' :
# version4
my $infile4 = "-";
my $fp4; # perl v3 p751 "pipe from bare command" to avoid shell processing, Note 'gzip -dfc' will call shell!
my $pid4 = open( my $file4, "-|", $fp4 = 'gzip', '-dfc', $infile4 ) || die "oops '$fp4' :$!\n";
print "v4
id4='$pid4', file4='$file4', fp4='$fp4', infile4 = '$infile4', \nline4 = >>",<$file4>,"<<\n";
close ($file4) || warn "close error on '$fp4' : $!\n";
#Results: waits for 'keyboardtext^D^D^D' from stdin, works on - for std input.
#v4
id4='6908', file4='GLOB(0x804cae8)', fp4='gzip', infile4 = '-',
#line4 = >>keyboardtext<<
Summary:
PBP lexical version of my "gzip -dfc is the universal input pipe" works
without calling unsafe shell interpretation on variable $infile4
Note that pipe command $fp is now an array
my $pid5 = open( my $file5, "-|", my @fp5 = ('gzip', '-dfc', $infile5) );
$pid5 || die "oops '@fp5' :$!\n";
Notes:
1 '/bin/gzip' won't call shell
2 '/bin/gzip -dfc' will call shell
3 Can't use 'my' $fp4 inside the open, and still die $fp4 on same line.
my $pid4 = open( my $file4, "-|", my $fp4 = 'gzip', '-dfc', $infile4 ) || die "$fp4:$!\n";
Error: Global symbol "$fp4" requires explicit package name at line 36.
Question:
Why is there no $! error message printed for version 3 from this line?
close ($file3) || warn "close error on '$fp3' : $!\n";