At a client we have a networked disk with millions of files. I was trying to list the first few files to see what's going on.
ls -l | head
takes ages, but here is a Perl one-liner to make it work:
perl -E 'opendir(my $dh, "/huge_dir"); my $c = 0; while (my $d = readdir($dh)) { say $d; exit if ++$c > 3 }'
In a different layout that could be put in a file
use feature 'say';
opendir(my $dh, "/huge_dir");
my $c = 0;
while (my $d = readdir($dh)) {
say $d;
exit if ++$c > 3
}
Explanation:
perl -E
tells perl that the next string is a piece of perl code that should executed. (as opposed to being a filename) This is what let's us write one-liners in Perl. Using the capital letter -E turns on the feature say among other things.
opendir(my $dh, "/huge_dir");
opens a directory and assigns the directory handle to the new variable called $dh
that was declared on the spot with my
my $c = 0;
declares a variable called $c
and assign 0. We'll use this for counting the entries.
while (my $d = readdir($dh))
a while loop that for each iteration will read one entry from the directory and assign it to the newly declared variable $d
. We declare this variable inside the loop to make it scoped to the loop.
{ say $d; exit if ++$c > 3 }
the block of the while loop
. First statement prints the value of $d
followed by a newline. Then we have a conditional statement in what is called statement modifier
where the statement comes before the condition. We first increment the counter and then check if it is greater than 3 and if it is then we call exit
.
I was even a bit overdoing with declarations. If we are not using strict
we don't need to declare variables. If a variable does not even have value but is incremented using ++
it will behave as if there was a 0 in it. So we don't need to initialize $c
.
perl -E 'opendir($dh, "/huge_dir"); while ($d = readdir($dh)) { say $d; exit if ++$c > 3}'
use feature 'say';
opendir($dh, "/huge_dir");
while ($d = readdir($dh)) {
say $d;
exit if ++$c > 3
}
And I don't need that $d
variable either. Instead of that I can use the invisible $_
:
perl -E 'opendir($dh, "/huge_dir"); while (readdir($dh)) { say; exit if ++$c > 3}'
use feature 'say';
opendir($dh, "/huge_dir");
while (readdir($dh)) {
say;
exit if ++$c > 3
}
Top comments (3)
$
or two.for
loop over the iteration count and abort on the other condition, rather than use awhile
loop on the condition and abort it on an iteration counter check.opendir
errors. (Yes, it’s just a one-liner where you know it will work. But then why usewhile (readdir)
? You know there’s more than 3 entries in that directory, too.) Throwing in an-Mautodie
is a quick way to absolve a lot of one-liners of explicit error checking. For a handful of keystrokes you get to buy a clean conscience.You could also use a (postfix) statement modifier for the
for
loop.Nice improvement!