I created the following Makefile to simulate your situation:
SHELL = /bin/bash
.PHONY: run
run: compare
$(MAKE) glob > /dev/null
$(MAKE) readdir > /dev/null
$(MAKE) path > /dev/null
.PHONY: prepare
prepare:
gen.sh
.PHONY: clean
clean:
rm -rf {100..200}
.PHONY: glob
glob:
time glob.pl
.PHONY: readdir
readdir:
time readdir.pl
.PHONY: path
path:
time path.pl
.PHONY: compare
compare:
diff <(glob.pl | sort) <(readdir.pl | sort)
diff <(glob.pl | sort) <(path.pl | sort)
The gen.sh is used to generate the directories:
#! /bin/bash
now=$(date +%s)
yday=$(date -d yesterday +%s)
tmrw=$(date -d tomorrow +%s)
mkdir {100..200}
for d in {100..200} ; do
for r in {1..250} ; do
mkdir $d/$(date +%Y%m%d -d @$((yday-10000*RANDOM)))
done 2>/dev/null
mkdir $d/$(date +%Y%m%d -d @$((tmrw+10*RANDOM)))
for r in {1..250} ; do
mkdir $d/$(date +%Y%m%d -d @$((yday-10000*RANDOM)))
done 2>/dev/null
echo $d >&2
done
glob.pl uses glob. It returns the entries sorted, so the last one is the future one, as dates sort alphabetically in the YYYYMMDD form (at least for the nearest future).
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Time::Piece;
my $now = localtime->ymd("");
for my $dir (glob '???/') {
say substr +(glob "$dir*/")[-1], 0, -1;
}
path.pl uses Path::Tiny.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Time::Piece;
use Path::Tiny qw{ path };
my $now = localtime->ymd("");
for my $dir (grep $_->is_dir, path('.')->children) {
for my $date (grep $_->is_dir, $dir->children) {
say $date if $date->basename > $now;
}
}
readdir.pl uses opendir and readdir.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Time::Piece;
my $now = localtime->ymd("");
opendir my $dir, '.' or die $!;
while (my $pdir = readdir $dir) {
next if $pdir =~ /^\.{1,2}$/ || ! -d $pdir;
opendir my $ddir, $pdir or die $!;
while (my $date = readdir $ddir) {
next if $date =~ /^\.{1,2}$/ || ! -d $dir;
say "$pdir/$date" if $date > $now;
}
}
Run make compare to verify all three scripts give the same output.
The results on my machine were
make glob > /dev/null
real 0m0.109s
user 0m0.054s
sys 0m0.053s
make readdir > /dev/null
real 0m0.074s
user 0m0.045s
sys 0m0.029s
make path > /dev/null
real 0m0.440s
user 0m0.380s
sys 0m0.060s
You can see, readdir.pl has the most verbose code as it's the most low-level, but it's the fastest one. Glob is a bit slower, but still pretty good. Path::Tiny didn't really shine, but maybe its code can be improved.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]