Pet*_*teY 4 regex perl aix readdir file-processing
我每天晚上都在处理一个大目录。每晚它会累积大约一百万个文件,其中一半.txt是我需要根据其内容移动到其他目录的文件。
每个.txt文件都是用管道分隔的,并且仅包含20条记录。记录6是包含我需要确定将文件移动到哪个目录的信息的记录。
记录示例:
A|CHNL_ID|4
Run Code Online (Sandbox Code Playgroud)
在这种情况下,文件将移至/out/4。
此脚本的处理速度为每小时80,000个文件。
关于如何加快速度有什么建议吗?
opendir(DIR, $dir) or die "$!\n";
while ( defined( my $txtFile = readdir DIR ) ) {
next if( $txtFile !~ /.txt$/ );
$cnt++;
local $/;
open my $fh, '<', $txtFile or die $!, $/;
my $data = <$fh>;
my ($channel) = $data =~ /A\|CHNL_ID\|(\d+)/i;
close($fh);
move ($txtFile, "$outDir/$channel") or die $!, $/;
}
closedir(DIR);
Run Code Online (Sandbox Code Playgroud)
单个目录中文件的数量过多会给您带来麻烦。
我创建了80_000文件并运行了您的脚本,该脚本在5.2秒内完成。这是在装有CentOS7和v5.16的旧笔记本电脑上。但是拥有50万个文件†,则需要近7分钟的时间。因此,问题不关乎代码本身的性能(但也可以提高代码的性能)。
然后有一个简单的解决方案:在文件即将来临之时,每小时(例如每小时)运行一次cron脚本。当您移动.txt文件时,也会将其他文件移动到其他地方,并且文件永远不会太多。该脚本将始终在几秒钟内运行。最后,如果需要,您可以将其他文件移回。
另一个选择是将这些文件存储在具有不同文件系统的分区上,例如ReiserFS。但是,这根本解决不了目录中文件太多的主要问题。
另一个部分解决方法是更换
while ( defined( my $txtFile = readdir DIR ) )
Run Code Online (Sandbox Code Playgroud)
与
while ( my $path = <"$dir/*txt"> )
Run Code Online (Sandbox Code Playgroud)
这导致1m:12s的运行(而不是近7分钟)。不要忘了调整文件命名,因为<>上面的代码返回了文件的完整路径。同样,这并不能真正解决问题。
如果您可以控制文件的分发方式,则需要一个3层(左右)深的目录结构,可以使用文件的MD5命名该目录结构,这将导致分配非常均衡。
†文件名及其内容创建为
perl -MPath::Tiny -wE'
path("dir/s".$_.".txt")->spew("A|some_id|$_\n") for 1..500_000
'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
357 次 |
| 最近记录: |