Reputation: 375
I'm trying to write a perl one liner for listing the content of a directory like with the "ls -l" Unix command however I only want to output directories and not files
I have managed to do it using a perl script but I want to try and see if it can be reduced to a single line using a pipe like
ls -l | grep "something"
or
ls -l | perl -...
the way I have done it so far is this
#!/usr/bin/perl
open(LS_D, "ls -l |");
while(<LS_D>) {
print if /^d.*/; #print line if line starts with d
}
Also could you tell me why this works with the pipe in "ls -l |" but not with "ls -l"?
Thanks
Upvotes: 0
Views: 499
Reputation: 66964
The long listing of directories can be directly obtained with
ls -ld */
without a need to filter the output.
As for the |
, that is how you tell open to open a process and replace its STDIN
or STDOUT
For three or more arguments if MODE is
|-
, the filename is interpreted as a command to which output is to be piped, and if MODE is-|
, the filename is interpreted as a command that pipes output to us. In the two-argument (and one-argument) form, one should replace dash (-
) with the command. See Using open() for IPC in perlipc for more examples of this.
Without |
, so with open(LS_D, "ls -l")
, you are trying to open a file, with the name 'ls -l'
The three-argument open
, which is recommended with its lexical filehandle, would be
open my $read_fh, '-|', 'ls', '-l';
where the command with arguments is supplied as a list.
Finally, what you have in your Perl script can be done with a one-liner for example as
perl -we'print grep { /^d/ } `ls -l`'
but, as shown above, you can get that directly with ls
on the command line.
I should add
Always have use warnings;
and use strict;
at the top of your programs
Always check calls like open
and you'll know about, and see the reason for, the failure
open my $fh ... or die "Can't open ... : $!";
See Error Variables in perlvar for $!
Upvotes: 4