获取给定路径下的目录名称

时间:2009-11-07 09:03:37

标签: perl

我试图在给定路径下获取所有第一级目录的名称。

我尝试使用File::Find,但遇到了问题。

有人可以帮我吗?

8 个答案:

答案 0 :(得分:24)

使用-d文件检查操作符:

#!/usr/bin/perl

use strict;
use warnings;
use autodie;

my $path = $ARGV[0];
die "Please specify which directory to search" 
    unless -d $path;

opendir( my $DIR, $path );
while ( my $entry = readdir $DIR ) {
    next unless -d $path . '/' . $entry;
    next if $entry eq '.' or $entry eq '..';
    print "Found directory $entry\n";
}
closedir $DIR;

答案 1 :(得分:7)

如果您不需要遍历整个目录层次结构,File::SlurpFile::Find更容易使用。

use strict;
use warnings;
use File::Slurp qw( read_dir );
use File::Spec::Functions qw( catfile );

my $path = shift @ARGV;
my @sub_dirs = grep { -d } map { catfile $path, $_ } read_dir $path;
print $_, "\n" for @sub_dirs;

如果您确实需要遍历层次结构,请检查CPAN是否有File::Find的更友好的替代方案。

  • File::FinderFile::Find::RuleFile::Find的前端。

  • File::Find::Closures值得学习如何使用File::Find以及如何使用my @sub_dirs = grep {-d} glob("$ARGV[0]/*"); 写闭包。

  • File::Next使用迭代器方法进行目录遍历和 看起来很有希望,虽然我从未使用它。

最后,根据TIMTOWTDI的精神,这里有一些快速而肮脏的东西:

{{1}}

答案 2 :(得分:3)

use File::Spec::Functions qw( catfile );

my ($path) = @ARGV;

opendir my $DIR, $path 
    or die "Cannot open directory: '$path': $!";

while ( my $entry = readdir $DIR ) {
    next if $entry =~ /\A\.\.?\z/;
    next unless -d catfile $path, $entry;
    print $entry, "\n";
}

closedir $DIR;

这对我有用。

答案 3 :(得分:1)

我在Windows XP下运行ActivePerl 5.10.1。如果我想获取根驱动器F下目录的所有名称,我将使用以下代码:

#!perl
opendir (DIR,'F:/');
my @folder = readdir(DIR);
foreach my $f (@folder)
{
   next if ($f =~ /\./);
   print "$f\n";
 }

嗯,这通常有效,因为我的文件夹名称不包含点。否则就失败了。

好吧,似乎即使我的方法适用于我的情况,人们仍然会因为它有缺陷而投票。所以我必须使用官方方法,-d标志来检查文件是否是目录:

升级后的代码:

#!perl
use strict;
use warnings;

opendir (DIR, "F:/");
my @files = readdir(DIR);
my @dirs = grep { -d } @files;
print @dirs;

答案 4 :(得分:0)

使用opendir-d

答案 5 :(得分:0)

您可以使用find2perl将您的find命令转换为perl。有关详细信息,请参阅perldoc find2perl。

maxdepth的解决方法:(来自Randall的参考)

$  find2perl /home/path -type d -eval 'my $slashes = $File::Find::name =~ tr#/##;return $File::Find::prune = 1 if $slashes > 2;return if $slashes ==2'

代码:

   use strict;
    use File::Find ();
    use vars qw/*name *dir *prune/;
    *name   = *File::Find::name;
    *dir    = *File::Find::dir;
    *prune  = *File::Find::prune;
    sub wanted;

    File::Find::find({wanted => \&wanted}, '/');
    exit;
    sub wanted {
        eval { my $slashes = $File::Find::name =~ tr#/##;return $File::Find::prune = 1 if $slashes > 1;return if $slashes ==1 };
        if ( $? == "0" && -d _  ){
            print "$name --- \n";   
        }
    }

输出

$ pwd
/temp

$ tree
.
|-- dir1
|   |-- subdir1
|   |   |-- subsubdir1
|   |   `-- testsubdir1.txt
|   `-- testdir1.txt
|-- dir2
|   |-- subdir2
|   |   |-- subsubdir2
|   |   `-- testsubdir2.txt
|   `-- testdir2.txt
|-- dir3
|   `-- subdir3
|       `-- subsubdir3
`-- test

9 directories, 5 files

$ perl perl.pl
/temp ---
/temp/dir3 ---
/temp/dir1 ---
/temp/dir2 ---

答案 6 :(得分:0)

使用File :: Find :: Rule

#!/usr/bin/perl --
use strict;
use warnings;

use Shell::Command qw( rm_rf touch mkpath );
use autodie;
use File::Find::Rule;

Main(@ARGV);
exit(0);

sub Main{
  use autodie;
  my $dir = "tmp";
  mkdir $dir;
#~   chdir $dir;
  mkpath "$dir/a/b/c/d";
  mkpath "$dir/as/b/c/d";
  mkpath "$dir/ar/b/c/d";

  print `tree`;
  print "---\n";
  print "$_\n"
    for File::Find::Rule->new->maxdepth(1)->directory->in($dir);

  print "---\n";

  print "$_\n"
    for grep -d, glob "$dir/*"; ## use forward slashes, See File::Glob

#~   chdir "..";
  rm_rf $dir;
}
__END__
.
|-- test.pl
`-- tmp
    |-- a
    |   `-- b
    |       `-- c
    |           `-- d
    |-- ar
    |   `-- b
    |       `-- c
    |           `-- d
    `-- as
        `-- b
            `-- c
                `-- d

13 directories, 1 file
---
tmp
tmp/a
tmp/ar
tmp/as
---
tmp/a
tmp/ar
tmp/as

或使用File :: Find :: Rule frontend findrule

$ findrule tmp -maxdepth ( 1 ) -directory
tmp
tmp/a
tmp/ar
tmp/as

答案 7 :(得分:-1)

您可以使用File :: Find。例如:

use File::Find ();

File::Find::find(\&wanted, '.');

sub wanted {
    if (-d) {    
        print "$File::Find::name\n";
    }
}

对于在'.'下找到的每个文件,这将调用wanted子例程。在子例程中,您可以使用-d来检查目录。

File::Find:find下降到指定目录下面树中的所有子目录。