How do I find, in a given path, all folders with no further subfolders? They may contain files but no further folders.
For example, given the following directory structure:
time/aa/
time/aa/bb
time/aa/bb/something/*
time/aa/bc
time/aa/bc/anything/*
time/aa/bc/everything/*
time/ab/
time/ab/cc
time/ab/cc/here/*
time/ab/cc/there/*
time/ab/cd
time/ab/cd/everywhere/*
time/ac/
The output of find(time) should be as follows:
time/aa/bb/something/*
time/aa/bc/anything/*
time/aa/bc/everything/*
time/ab/cc/here/*
time/ab/cc/there/*
time/ab/cd/everywhere/*
* above represents files.
Any time you want to write a directory walker, always use the standard File::Find module. When dealing with the filesystem, you have to be able to handle odd corner cases, and naïve implementations rarely do.
The environment provided to the callback (named wanted in the documentation) has three variables that are particularly useful for what you want to do.
$File::Find::diris the current directory name
$_is the current filename within that directory
$File::Find::nameis the complete pathname to the file
When we find a directory that is not . or .., we record the complete path and delete its parent, which we now know cannot be a leaf directory. At the end, any recorded paths that remain must be leaves because find in File::Find performs a depth-first search.
#! /usr/bin/env perl
use strict;
use warnings;
use File::Find;
@ARGV = (".") unless @ARGV;
my %dirs;
sub wanted {
return unless -d && !/^\.\.?\z/;
++$dirs{$File::Find::name};
delete $dirs{$File::Find::dir};
}
find \&wanted, @ARGV;
print "$_\n" for sort keys %dirs;
You can run it against a subdirectory of the current directory
$ leaf-dirs time time/aa/bb/something time/aa/bc/anything time/aa/bc/everything time/ab/cc/here time/ab/cc/there time/ab/cd/everywhere
or use a full path
$ leaf-dirs /tmp/time /tmp/time/aa/bb/something /tmp/time/aa/bc/anything /tmp/time/aa/bc/everything /tmp/time/ab/cc/here /tmp/time/ab/cc/there /tmp/time/ab/cd/everywhere
or plumb multiple directories in the same invocation.
$ mkdir -p /tmp/foo/bar/baz/quux $ leaf-dirs /tmp/time /tmp/foo /tmp/foo/bar/baz/quux /tmp/time/aa/bb/something /tmp/time/aa/bc/anything /tmp/time/aa/bc/everything /tmp/time/ab/cc/here /tmp/time/ab/cc/there /tmp/time/ab/cd/everywhere
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With