develooper Front page | perl.perl5.porters | Postings from October 2014

[perl #122968] File::Find always re-sorts directories last

Thread Previous | Thread Next
From:
James E Keenan via RT
Date:
October 14, 2014 01:51
Subject:
[perl #122968] File::Find always re-sorts directories last
Message ID:
rt-4.0.18-21584-1413251463-1783.122968-15-0@perl.org
On Mon Oct 13 10:09:09 2014, leonerd@leonerd.org.uk wrote:
> This is a bug report for perl from leonerd@leonerd.org.uk,
> generated with the help of perlbug 1.40 running under perl 5.20.0.
> 
> 
> -----------------------------------------------------------------
> 
> File::Find, even in depth-first mode, even with a preprocess function,
> will
> always visit non-directories before directories. For example:
> 
> find({
>    no_chdir => 1,
>    preprocess => sub {
>       my @ret = sort @_;
>       print "Sorted dirs: <@ret>\n";
>       return @ret; },
> 
> wanted => sub {
>    my $filename = $_;
>    print "Considering $filename...\n"; },
> }, "tests"
> );
> 
> will yield the output:
> 
> Considering tests...
> Sorted dirs: <. .. 10apidoc 50register.pl 51displayname.pl 60create-
> room.pl 61room-message.pl 62room-presence.pl>
> Considering tests/50register.pl...
> Considering tests/51displayname.pl...
> Considering tests/60create-room.pl...
> Considering tests/61room-message.pl...
> Considering tests/62room-presence.pl...
> Considering tests/10apidoc...
> Sorted dirs: <. .. 01register.pl>
> Considering tests/10apidoc/01register.pl...
> 
> Specfically, even though I have sorted '10apidoc' before
> '50register.pl' it
> has reordered it to come last as it is a directory, after all of the
> non-directories. This code is implemented in the logic around here:
> 
> https://metacpan.org/source/SHAY/perl-5.20.1/ext/File-
> Find/lib/File/Find.pm#L766
> 
> and the later  if(-d _)-guarded block involving a splice on this
> array.
> 
> 
> This bug therefore comes in two parts:
> 
> 
> 1) The documentation of File::Find nowhere makes mention of the fact
> it will
>    do this.
> 
> 2) There is no control over this behaviour, and therefore no way for
> me to
>    ask it not to happen, and respect my chosen sorting order.
> 

I suspect that the problem lies in this part of ext/File-Find/lib/File/Find.pm:

#####
 295 sub _find_dir($$$) {
 296     my ($wanted, $p_dir, $nlink) = @_;
...
 389     @filenames = readdir DIR;
 390     closedir(DIR);
 391     @filenames = $pre_process->(@filenames) if $pre_process;
...
 419     else {
 420         # This dir has subdirectories.
 421         $subcount = $nlink - 2;
 422 
 423         # HACK: insert directories at this position. so as to preserve
 424         # the user pre-processed ordering of files.
 425         # EG: directory traversal is in user sorted order, not at random.
 426             my $stack_top = @Stack;
 427 
 428         for my $FN (@filenames) {
 429         next if $FN =~ $File::Find::skip_pattern;
 430         if ($subcount > 0 || $no_nlink) {
 431             # Seen all the subdirs?
 432             # check for directoriness.
 433             # stat is faster for a file in the current directory
 434             $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
 435 
 436             if (-d _) {
 437             --$subcount;
 438             $FN =~ s/\.dir\z//i if $Is_VMS;
 439             # HACK: replace push to preserve dir traversal order
 440             #push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
 441             splice @Stack, $stack_top, 0,
 442                      [$CdLvl,$dir_name,$FN,$sub_nlink];
 443             }
 444             else {
 445             $name = $dir_pref . $FN; # $File::Find::name
 446             $_= ($no_chdir ? $name : $FN); # $_
 447             { $wanted_callback->() }; # protect against wild "next"
 448             }
 449         }
 450         else {
 451             $name = $dir_pref . $FN; # $File::Find::name
 452             $_= ($no_chdir ? $name : $FN); # $_
 453             { $wanted_callback->() }; # protect against wild "next"
 454         }
 455         }
 456     }
...
#####

This code was added in 2003 in what is now commit 7bd31527 in response to RT #22195 (see attachment).

That's as far as I'll be able to analyze this tonight.

Thank you very much.
-- 
James E Keenan (jkeenan@cpan.org)

---
via perlbug:  queue: perl5 status: new
https://rt.perl.org/Ticket/Display.html?id=122968

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About