使用Perl计算文件夹中的文件数量

vuv7lop3  于 2023-08-06  发布在  Perl
关注(0)|答案(5)|浏览(156)

我想用Perl来计算一个文件夹中的文件数量。通过下面的代码我可以列出它们,但是我如何在Perl中计算它们呢?

$dir = "/home/Enric/gfs-0.5.2016061400";
opendir(DIR, "$dir");
@FILES = grep { /gfs./ } readdir(DIR);
foreach $file (@FILES) {
    print $file, "\n";
}
closedir(DIR);

字符串

3htmauhk

3htmauhk1#

如果你只想计算它们,一旦你打开了一个目录进行阅读,你就可以操纵上下文,这样readdir就可以返回所有条目的列表,然后把它分配给一个标量。这给了你列表的长度,即。元素个数

opendir my $dh, $dir;
my $num_entries = () = readdir($dh);

字符串
构造= () =将列表上下文强加给readdir,并将(表达式†)赋值给标量,从而获得该列表中元素的数量。 在perlsecret中查看。参见this page
当然,还有更清晰的方法,如下所示。
如果您想计算某些类型的文件,请首先通过grep传递文件列表,就像您所做的那样。由于grep在其输入上强加了列表上下文,因此readdir返回所有文件的列表,并且在过滤之后,grep本身返回列表。当你把它赋给一个标量时,你就得到了这个列表的长度(元素的数量),即。你的计数。例如,对于所有常规文件和/gfs./文件

use warnings;
use strict;

my $dir = '/home/Enric/gfs-0.5.2016061400';
opendir my $dh, $dir  or die "Can't open $dir: $!";

my $num_files =  grep { -f "$dir/$_" } readdir($dh);
rewinddir($dh);  # so that it can read the dir again
my $num_gfs   =  grep { /gfs./ } readdir($dh);


(This仅是一个示例,使用rewinddir,以便它按原样工作。要真正从一个目录中获取两种文件,最好一次遍历一个条目,并在过程中对它们进行排序,或者将所有文件读入一个数组,然后处理该数组)

  • 注意readdir返回的是空文件名,没有任何路径。* 因此,对于大多数通常对文件所做的操作,我们需要在其前面加上路径(除非您首先将chdir添加到该目录)。这就是在上面的grep块中所做的,以便-ffile test (-X)具有正确的文件名。

如果您需要使用文件列表本身,请将其放入数组中,然后将其分配给标量

# Get the file list, then its length
my @files_gfs = map { "$dir/$_" } grep { /gfs./ } readdir($dh);
my $num_gfs = @files_gfs;


这里map为每个文件构建完整路径。如果不需要路径,请删除map { }。请注意,通常不需要在数组上正式使用scalar来获取计数,如

my $num_gfs = scalar @files_gfs;    # no need for "scalar" here!


相反,简单地将数组分配给标量,这是一种习惯用法(至少可以这么说)。
如果你是边读边处理文件,边数边走

my $cnt_gfs = 0;
while (my $filename = readdir($dh)) {
    $cnt_gfs++ if $filename =~ /gfs./;
    # Process $dir/$filename as needed
}


这里readdir位于标量上下文中(因为它的输出被分配给标量),它遍历目录条目,每次返回一个。
几个音符

  • 在上面的所有代码中,我都使用了问题中的示例/gfs./--但如果这实际上意味着表示文字句点,那么应该用/gfs\./替换
  • 所有这些关于readdir如何返回裸文件名(无路径)的讨论在glob(或更好的File::Glob)中都不需要,它会返回完整路径
use File::Glob ':bsd_glob';  # (better with this)

my @files = glob "$dir/*";


这将返回路径为$dir/filename的文件列表。
并不是说opendir + readdir有什么问题。只是别忘了路。
还有一种选择是使用库,比如Path::Tiny及其子方法。
†赋值() = readdir $dh本身也返回一个值,在这种情况下,that 整个表达式(赋值)被放置在标量上下文中。
‡问题是Perl中的许多工具依赖于它们的操作并返回上下文,因此不能总是仅仅将列表分配给标量并期望获得列表的长度。readdir就是一个很好的例子,它返回列表上下文中所有条目的列表,但在标量上下文中只返回单个条目。
§这里是另一个技巧

my $num_entries = @{ [ readdir $dh ] };


这里是一个匿名数组(引用)[]的构造函数,它将列表上下文强加给readdir,而解引用@{ }不关心上下文,只返回该arrayref的元素列表。所以我们可以把它赋值给一个标量,这样的scalar assignment返回该列表中元素的数量。

kq4fsx7k

kq4fsx7k2#

您有@FILES中的文件列表。所以你的问题变成了“我如何得到一个数组的长度?“这很简单,你只需在标量上下文中计算数组。

my $number_of_files = @FILES;
print $number_of_files;

字符串
或者,您可以使用scalar()函数消除不必要的标量变量。

print scalar @FILES;

5cg8jx4n

5cg8jx4n3#

尝试以下代码作为初学者(这是在Windows上,将包括...和文件夹。如果只需要文件,可以过滤掉这些文件):

#!/usr/bin/perl -w

my $dirname = "C:/Perl_Code";
my $filecnt = 0;

opendir (DIR, $dirname) || die "Error while opening dir $dirname: $!\n";
while(my $filename = readdir(DIR)){
     print("$filename\n");
     $filecnt++;
}
closedir(DIR);
print "Files in $dirname : $filecnt\n";
exit;

字符串

smdncfj3

smdncfj34#

我知道这不是在Perl中,但如果你需要一个快速的方法,只需在bash命令行中输入以下内容:

ls -1 | wc -l

字符串
ls -1提供目录中文件的列表,wc -l提供行数。合并后,它们会给予你目录中的文件数量。
或者,您可以从Perl调用bash(尽管您可能不应该这样做),使用

system("ls -1 | wc -l");

zour9fqk

zour9fqk5#

作为zdim's answer的一个变体,假设您 * 没有 * 打开目录句柄。那样的话

my $num_files =()= glob("$dir/*");

字符串
可能更有用这与zdim的建议遵循相同的原理,但不需要先调用opendir
这将返回 * 不包含 * 的文件数,包括...,至少在Linux上是这样。

相关问题