Skip to content

Perl 目录

Perl 提供了内置函数,用于与文件系统的目录结构交互。这些函数允许你列出目录内容、创建、删除和更改目录。

核心目录函数:

opendir(my $dh, $dirname) or die "Cannot open directory '$dirname': $!"; # 打开一个目录
my @entries = readdir($dh); # 从目录读取条目
rewinddir($dh); # 重置目录流的指针到开头
telldir($dh); # 获取目录流中的当前位置
seekdir($dh, $pos); # 设置目录流中的位置
closedir($dh); # 关闭目录句柄
mkdir($new_dir, $permissions) or die "Cannot create directory '$new_dir': $!"; # 创建一个目录
rmdir($dir_to_remove) or die "Cannot remove directory '$dir_to_remove': $!"; # 删除一个空目录
chdir($target_dir) or die "Cannot change to directory '$target_dir': $!"; # 更改当前目录

始终在脚本中使用 use strict; 和 use warnings;。使用词法目录句柄 (lexical directory handles)(my $dh)以提高代码安全性。

这是列出目录内容的传统方法。

#!/usr/bin/perl
use strict;
use warnings;
my $dir_path = '.'; # 当前目录
opendir(my $dh, $dir_path) or die "Can't open $dir_path: $!";
print "Entries in '$dir_path':\n";
while (my $entry = readdir($dh)) {
# readdir 也返回 '.' 和 '..'
next if $entry eq '.' or $entry eq '..';
print "$entry\n";
}
closedir($dh);

glob() 函数(或 <*>)展开文件名模式,类似于 shell 的 globbing。

#!/usr/bin/perl
use strict;
use warnings;
my $dir_pattern = './*'; # 当前目录中的所有文件和目录
print "Entries matching '$dir_pattern' (via glob):\n";
my @files = glob($dir_pattern);
# 或者:my @files = <$dir_pattern>;
foreach my $file (@files) {
print "$file\n";
}
# 仅获取 /tmp 中的 .txt 文件:
# my @text_files = glob('/tmp/*.txt');
# 获取 /tmp 中的隐藏文件(以 . 开头):
# my @hidden_files = glob('/tmp/.*');

glob() 对于简单模式很方便,但如果模式来自不受信任的输入,可能会有安全隐患。

可以将 readdir 与 grep 结合使用来过滤条目。

#!/usr/bin/perl
use strict;
use warnings;
my $dir_path = '.';
opendir(my $dh, $dir_path) or die "Can't open $dir_path: $!";
print "Perl files (.pl, .pm) in '$dir_path':\n";
my @perl_files = grep { /\.(pl|pm)$/i && -f "$dir_path/$_" } readdir($dh);
# -f 检查确保它是文件,而不是以 .pl 结尾的目录
closedir($dh);
foreach my $file (@perl_files) {
print "$file\n";
}

mkdir() 函数创建一个新目录。可选的第二个参数指定权限(例如 0755)。

#!/usr/bin/perl
use strict;
use warnings;
my $new_dir = './my_new_directory';
my $permissions = 0755; # 典型权限
if (mkdir($new_dir, $permissions)) {
print "Directory '$new_dir' created successfully.\n";
# 为示例目的进行清理
rmdir($new_dir) or warn "Could not remove test directory '$new_dir': $!";
} else {
warn "Couldn't create directory '$new_dir': $!";
}

rmdir() 函数删除一个空目录。

#!/usr/bin/perl
use strict;
use warnings;
my $dir_to_remove = './empty_dir_to_remove';
# 首先为示例创建它
mkdir($dir_to_remove, 0755) or die "Setup: Could not create $dir_to_remove: $!";
if (rmdir($dir_to_remove)) {
print "Directory '$dir_to_remove' removed successfully.\n";
} else {
warn "Couldn't remove directory '$dir_to_remove': $!";
warn "(它是否为空?你是否有权限?)";
}

要删除一个包含内容的目录,需要先递归删除其内容。像 File::Path 这样的模块提供了 remove_tree 等函数来实现这一点。

chdir() 函数更改脚本的当前工作目录。

#!/usr/bin/perl
use strict;
use warnings;
use Cwd qw(getcwd);
my $target_dir = '/tmp'; # 示例目标目录
my $original_dir = getcwd(); # 获取当前工作目录
print "Original directory: $original_dir\n";
if (chdir($target_dir)) {
my $new_current_dir = getcwd();
print "Successfully changed to '$target_dir'. New current directory: $new_current_dir\n";
# 切回原始目录(如果需要,这是一个好习惯)
chdir($original_dir) or warn "Could not change back to $original_dir: $!";
} else {
warn "Couldn't change to directory '$target_dir': $!";
}

虽然 Perl 的内置函数功能强大,但对于更复杂或面向对象的文件和目录操作,可以考虑使用 CPAN 模块,例如:

  • Path::Tiny: 一个小巧、快速且方便的路径操作模块。
  • Path::Class: 提供面向对象的文件和目录接口。
  • File::Spec: 用于平台无关的路径操作(例如,拼接路径组件)。

这些模块通常能使代码更清晰、更健壮,特别是对于跨平台应用。