one-liner: read first elements of a huge directory

Gabor Szabo - Jan 17 '23 - - Dev Community

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 }'
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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}'
Enter fullscreen mode Exit fullscreen mode
use feature 'say';
opendir($dh, "/huge_dir");
while ($d = readdir($dh)) {
    say $d;
    exit if ++$c > 3
}
Enter fullscreen mode Exit fullscreen mode

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}'
Enter fullscreen mode Exit fullscreen mode
use feature 'say';
opendir($dh, "/huge_dir");
while (readdir($dh)) {
    say;
    exit if ++$c > 3
}
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .