我在一台windows机器上工作,我有一个目录,里面装满了大约20万个我需要整理的文件。这是一项我需要经常使用不同文件名集但模式相似的工作,所以perl似乎是一个很好的使用工具。
每个文件名由{一个字符串a}{2或3位数字B}{
我想为每个字符串创建一个文件夹
在每个文件夹中,我想要每个B 的子文件夹
然后我想将每个文件移动到其相关的子文件夹中
所以它最终会看起来像
/CustomerA/1
/CustomerA/2
/CustomerA/3
/CustomerB/1
/CustomerB/2
/CustomerB/3
等等,每个子文件夹中的文件
因此,CustomerA888x123.xml被移到/CustomerA/888/中
我有一个数组中的文件列表,但我很难将文件名分解为其组成部分并有效地使用这些部分。
谢谢你的回答。我最终得到了这个:
#!usr/bin/perl
use warnings;
use strict;
use File::Copy qw(move);
use File::Path qw(make_path);
opendir my $dir, ".";
my @files = readdir($dir);
closedir $dir;
foreach my $file (@files) {
my ($cust, $num) = $file =~ m/(D+)(d+)/;
my $dirname = "$cust/$num";
my @dirs_made = make_path($dirname, { verbose => 1 });
move($file, $dirname) or warn "cant move $file to $dirname: $!";
}
给定文件名的描述,这个正则表达式应该解析您需要的
my ($cust, $num) = $filename =~ m/(D+)(d+)/;
如果您希望或需要更具体地说明数字前面的内容,请使用更精确的模式,例如仅用于字母的[a-zA-Z]
。
有了这些,您可以使用核心模块File::Path
创建目录,例如
use File::Path qw(make_path);
my $dirname = "$cust/$num";
my @dirs_made = make_path($dirname, { verbose => 1 });
这将根据需要创建路径,并返回已创建目录的名称。它还使用verbose
打印名称。如果目录存在,它会悄悄跳过它。如果有问题,它会引发die
,所以你可能想把它包装在eval
中
eval { make_path($dirname) };
if ($@) {
warn "Error with make_path($dirname): $@";
}
还要注意,File::Path::Tiny
模块是一个替代方案,感谢SinanÜnür的提出。除了更轻之外,它还有更常见的错误处理策略,即在失败时返回false,因此您不需要eval
,只需要常规的检查
use File::Path::Tiny;
File::Path::Tiny::mk($path) or warn "Can't mk($path): $!";
该模块在许多方面与mkdir
类似,请参阅链接文档。
使用move
功能移动核心模块File::Copy
中的文件,例如
use File::Copy qw(move);
move($file, $dirname) or warn "Can't move $file to $dirname: $!";
所有这些都可以在具有文件名的数组上循环。