网络宝典
第二套高阶模板 · 更大气的阅读体验

Perl遍历目录文件:几行代码搞定文件扫描(详细解析)

发布时间:2026-04-11 22:30:54 阅读:2 次

你有没有遇到过这样的需求:把某个ref="/tag/182/" style="color:#643D3D;font-weight:bold;">文件夹里所有 .log 文件找出来,批量重命名;或者统计某个项目目录下有多少个 .pl 脚本?用 Windows 资源管理器点开一层层找,太累;写个批处理又不太顺手。这时候 Perl 就挺合适——它原生支持目录操作,几行代码就能递归扫完整个目录树。

最简单的目录遍历

Perl 里用 opendirreaddir 就能读一个目录:

opendir(my $dh, ".") or die "无法打开当前目录: $!";
while (my $file = readdir($dh)) {
    next if $file =~ /^\./;  # 跳过 . 和 ..
    print "$file\n";
}
closedir($dh);

这段代码会列出当前目录下的所有非隐藏文件和子目录(不含递归)。注意 readdir 返回的是不带路径的文件名,所以如果想判断是文件还是目录,得拼上路径再用 -f-d 测试。

带路径的判断和过滤

比如只打印普通文件:

opendir(my $dh, "/var/log") or die "无法打开 /var/log: $!";
while (my $name = readdir($dh)) {
    next if $name =~ /^\./;
    my $path = "/var/log/$name";
    print "$path\n" if -f $path;
}
closedir($dh);

这里 -f $path 是 Perl 的文件测试操作符,类似 Shell 里的 [ -f ],返回真就说明是普通文件。

递归遍历整个目录树

想深入子目录?自己写个递归函数就行:

sub scan_dir {
    my ($dir) = @_;
    opendir(my $dh, $dir) or warn "跳过 $dir: $!" and return;
    while (my $entry = readdir($dh)) {
        next if $entry =~ /^\./;
        my $full = "$dir/$entry";
        if (-d $full) {
            scan_dir($full);  # 是目录,递归进去
        } else {
            print "$full\n" if $full =~ /\.conf$/; # 只输出 .conf 文件
        }
    }
    closedir($dh);
}

scan_dir("/etc");

这个函数会从 /etc 开始,一层层钻进子目录,最后把所有以 .conf 结尾的文件路径打印出来。你可以把结尾条件换成 \.pl$^Makefile$ 或者 -s > 1024*1024(大于 1MB 的文件)。

更省事的办法:File::Find 模块

Perl 标准库里有个现成模块 File::Find,不用自己写递归逻辑:

use File::Find;

find(sub {
    return unless -f;  # 只处理文件
    return unless /\.txt$/i;  # 忽略大小写匹配 .txt
    print "$File::Find::name\n";  # 完整路径
}, "/home/user/docs");

运行后,$File::Find::name 就是当前文件的绝对路径,$_ 是文件名本身。这个模块在脚本中用起来干净利落,适合快速写个临时工具。

小提醒:Linux/macOS 下 Perl 通常自带;Windows 用户如果没装,可以去 perl.org 下个 Strawberry Perl,装好就能直接跑上面这些例子。