我正在使用Windows机器,我有一个目录,里面装满了〜200k的文件,我需要整理这些文件。这是我需要定期使用不同文件名集但具有相似模式的工作,因此perl似乎是一个很好的工具。
每个文件名由{a string A} {2或3位数字B}组成{单个字母" r"或" x"} {3位数字} .extension
我想为每个字符串A
创建一个文件夹在每个文件夹中,我想要每个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: $!";
}
答案 0 :(得分:3)
鉴于您对文件名的描述,此正则表达式应该解析您需要的内容
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
的行为类似,请参阅链接文档。
使用核心模块File::Copy
的move
函数移动文件,例如
use File::Copy qw(move);
move($file, $dirname) or warn "Can't move $file to $dirname: $!";
所有这些都可以在带有文件名的数组循环中。