目录操作 #
一、目录遍历 #
1.1 opendir/readdir/closedir #
perl
opendir my $dh, "." or die "Cannot open directory: $!";
while (my $entry = readdir $dh) {
next if $entry eq "." or $entry eq "..";
print $entry . "\n";
}
closedir $dh;
1.2 获取所有条目 #
perl
opendir my $dh, "." or die $!;
my @entries = readdir $dh;
closedir $dh;
print "$_\n" foreach @entries;
1.3 过滤文件类型 #
perl
opendir my $dh, "." or die $!;
my @dirs = grep { -d $_ } readdir $dh;
rewinddir $dh;
my @files = grep { -f $_ } readdir $dh;
closedir $dh;
print "Directories: @dirs\n";
print "Files: @files\n";
1.4 使用glob #
perl
my @txt_files = glob "*.txt";
my @all_files = glob "*";
my @perl_files = glob "*.pl *.pm";
print "$_\n" foreach @txt_files;
二、目录创建与删除 #
2.1 创建目录 #
perl
mkdir "newdir" or die "Cannot create: $!";
mkdir "newdir", 0755 or die "Cannot create: $!";
2.2 创建多级目录 #
perl
use File::Path qw(make_path);
make_path "a/b/c/d" or die "Cannot create: $!";
2.3 删除目录 #
perl
rmdir "emptydir" or die "Cannot remove: $!";
2.4 删除非空目录 #
perl
use File::Path qw(remove_tree);
remove_tree "dir" or die "Cannot remove: $!";
三、路径操作 #
3.1 当前目录 #
perl
use Cwd;
my $cwd = getcwd();
print "Current directory: $cwd\n";
3.2 切换目录 #
perl
chdir "/tmp" or die "Cannot change: $!";
{
local $ENV{PWD} = "/tmp";
}
3.3 路径分解 #
perl
use File::Basename;
my $path = "/path/to/file.txt";
my $dirname = dirname($path);
my $basename = basename($path);
my ($name, $dirs, $suffix) = fileparse($path, qr/\.[^.]*/);
print "Dirname: $dirname\n";
print "Basename: $basename\n";
print "Name: $name, Dirs: $dirs, Suffix: $suffix\n";
3.4 路径拼接 #
perl
use File::Spec;
my $path = File::Spec->catfile("path", "to", "file.txt");
print $path;
my $abs_path = File::Spec->rel2abs("file.txt");
print $abs_path;
四、File::Find模块 #
4.1 基本遍历 #
perl
use File::Find;
find(sub {
print $File::Find::name . "\n";
}, ".");
4.2 查找特定文件 #
perl
use File::Find;
my @perl_files;
find(sub {
push @perl_files, $File::Find::name if /\.pl$/;
}, ".");
print "$_\n" foreach @perl_files;
4.3 查找目录 #
perl
use File::Find;
my @dirs;
find(sub {
push @dirs, $File::Find::name if -d $_;
}, ".");
print "$_\n" foreach @dirs;
4.4 预处理 #
perl
use File::Find;
find({
wanted => sub {
print $File::Find::name . "\n";
},
preprocess => sub {
return sort @_;
},
}, ".");
五、Path::Tiny模块 #
5.1 创建路径对象 #
perl
use Path::Tiny;
my $path = path("/path/to/file.txt");
my $dir = path("/path/to/dir");
5.2 文件操作 #
perl
use Path::Tiny;
my $file = path("test.txt");
my $content = $file->slurp;
my @lines = $file->lines;
$file->spew("New content\n");
$file->append("More content\n");
5.3 目录操作 #
perl
use Path::Tiny;
my $dir = path(".");
my @children = $dir->children;
my @files = $dir->children(qr/\.txt$/);
$dir->child("subdir")->mkpath;
5.4 路径操作 #
perl
use Path::Tiny;
my $path = path("/path/to/file.txt");
my $parent = $path->parent;
my $basename = $path->basename;
my $absolute = $path->absolute;
my $relative = $path->relative;
print "Parent: $parent\n";
print "Basename: $basename\n";
六、实用示例 #
6.1 递归文件大小统计 #
perl
use File::Find;
my $total_size = 0;
find(sub {
$total_size += -s $_ if -f $_;
}, ".");
print "Total size: $total_size bytes\n";
6.2 查找重复文件 #
perl
use strict;
use warnings;
use File::Find;
use Digest::MD5;
my %files;
find(sub {
return unless -f $_;
open my $fh, "<", $_ or return;
my $md5 = Digest::MD5->new;
$md5->addfile($fh);
my $hash = $md5->hexdigest;
close $fh;
push @{$files{$hash}}, $File::Find::name;
}, ".");
foreach my $hash (keys %files) {
if (@{$files{$hash}} > 1) {
print "Duplicates:\n";
print " $_\n" foreach @{$files{$hash}};
}
}
6.3 清理临时文件 #
perl
use strict;
use warnings;
use File::Find;
my @to_delete;
find(sub {
if (/\.tmp$/i || /\.bak$/i) {
push @to_delete, $File::Find::name;
}
}, ".");
foreach my $file (@to_delete) {
print "Delete $file? [y/N] ";
my $answer = <STDIN>;
if ($answer =~ /^y/i) {
unlink $file;
print "Deleted\n";
}
}
七、实践练习 #
练习1:目录树 #
perl
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my $dir = $ARGV[0] // ".";
find(sub {
my $depth = () = $File::Find::name =~ /\//g;
my $indent = " " x $depth;
my $name = -d $_ ? "$_/" : $_;
print "$indent$name\n";
}, $dir);
练习2:文件搜索 #
perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
use File::Find;
my ($dir, $pattern) = @ARGV;
die "Usage: $0 <dir> <pattern>\n" unless $dir && $pattern;
my @found;
find(sub {
push @found, $File::Find::name if /$pattern/;
}, $dir);
if (@found) {
say "Found:";
say " $_" foreach @found;
} else {
say "No files found matching $pattern";
}
练习3:目录同步 #
perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
use File::Copy;
use File::Find;
use File::Path qw(make_path);
use File::Basename;
my ($src, $dst) = @ARGV;
die "Usage: $0 <source> <dest>\n" unless $src && $dst;
find(sub {
my $src_path = $File::Find::name;
my $rel_path = File::Spec->abs2rel($src_path, $src);
my $dst_path = File::Spec->catfile($dst, $rel_path);
if (-d $src_path) {
make_path $dst_path unless -d $dst_path;
} else {
my $dst_dir = dirname($dst_path);
make_path $dst_dir unless -d $dst_dir;
copy $src_path, $dst_path or warn "Cannot copy $src_path: $!";
say "Copied: $src_path -> $dst_path";
}
}, $src);
八、总结 #
本章学习了:
- 目录遍历(opendir、readdir、glob)
- 目录创建和删除
- 路径操作
- File::Find模块
- Path::Tiny模块
下一章将学习正则表达式。
最后更新:2026-03-27