file - 正则表达式比较部分文件名然后移动到另一个目录 perl
问题描述
我正在编写一个脚本来将目录中的非运行文件与命令中的运行文件进行比较。我必须使用正则表达式从目录中删除文件名的前半部分,然后使用正则表达式从命令中删除文件名,然后将不匹配的名称记录到数组中。
我无法弄清楚的部分是如何将文件名从旧目录移动到新目录以供将来删除。
为了移动文件,我需要将它们括在通配符中,* 由于文件名和扩展名前面的随机数。之前和之后的示例文件名:
在目录内:
13209811124300209156562070_cake_872_trucks.rts
在命令内:
{"file 872","cake_872_trucks.rts",running}
在@events
数组中:
cake_872_卡车
我的代码:
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Copy qw(move);
use Data::Dumper;
use List::Util 'max';
my $orig_dir = "/var/user/data/";
my $dest_dir = "/var/user/data/DeleteMe/";
my $dir = "/var/user/data";
opendir(DIR, $dir) or die "Could not open $dir: $!\n";
my @allfiles = readdir DIR;
close DIR;
my %files;
foreach my $allfiles(@allfiles) {
$allfiles =~ m/^(13{2}638752056463{2}635181_|1[0-9]{22}_|1[0-9]{23}_|1[0-9]{24}_|1[0-9]{25}_)([0-9a-z]{4}_8[0-9a-z]{2}_[0-9a-z]{2}[a-z][0-9a-z]0[0-9]\.rts|[a-z][0-9a-z]{3}_[0-9a-z]{4}_8[0-9a-z]{2}_[0-9a-z]{2}[a-z]{2}0[0-9]\.rts|[a-z]{2}[0-9a-z][0-9]\N[0-9a-z]\N[0-9]\N[0-9]\N[0-9a-z]{4}\N[0-9]\.rts|[a-z]{2}[0-9a-z]{2}\N{2}[0-9a-z]{2}\N{2}[0-9][0-9a-z]{2}\N[0-9]{2}\.rts|S0{2}2_86F_JATD_01ZF\.rts)$/im;
$files{$2} = [$1];
}
my @stripfiles = keys %files;
my $cmd = "*****";
my @runEvents = `$cmd`;
chomp @runEvents;
foreach my $running(@runEvents) {
$running =~ s/^\{"blah 8[0-9a-z]{2}","(?<field2>CBE1_D{3}1_8EC_J6TG0{2}\.rts|[0-9a-z]{4}_8[0-9a-z]{2}_[0-9a-z]{2}[a-z][0-9a-z]0[0-9]\.rts|[a-z]{2}[0-9a-z]{2}\N{2}[0-9a-z]{2}\N{2}[0-9][0-9a-z]{2}\N[0-9]{2}\.rts)(?:",\{239,20,93,5\},310{2},20{3},run{2}ing\}|",\{239,20,93,5\},310{2},[0-9]{2}0{3},run{2}ing\}|",\{239,20,93,5\},310{2},[0-9]{3}0{4},run{2}ing\}|",\{239,20,93,5\},3[0-9]0{2},[0-9]{2}0{4},run{2}ing\})$/$+{field2}/img;
}
my @events = grep {my $x = $_; not grep {$x =~/\Q$_/i}@runEvents}@stripfiles;
foreach my $name (@events) {
my ($randnum, $fnames) = { $files{$name}};
my $combined = $randnum . $fnames;
print "Move $file from $orig_dir to $dest_dir";
move ("$orig_dir/$files{$name}", $dest_dir)
or warn "Can't move $file: $!";
}
#print scalar(grep $_, @stripfiles), "\n";
#returned 1626
#print scalar(grep $_, @runEvents), "\n";
#returned 102
#print scalar(grep $_, @allfiles), "\n";
#returned 1906
解决方案
一旦您使用正则表达式解析文件名,就没有理由不能捕获所有部分,以便您以后可以重构文件名的所需部分。
我认为过长(且不完整)的正则表达式可以达到预期的目的。
我不确定要移动的文件与 中的原始文件有何关系@allfiles
,因为这些文件是/var/user/data
在您的移动尝试使用时从中获取的/home/user/RunBackup
。所以下面的代码片段更通用。
如果移动的正是这些文件,@allfiles
那么只需保留文件名
my %files;
foreach my $oldfile (@allfiles) {
$oldfile =~ m/...(...).../; # your regex, but capture the name
$files{$1} = $oldfile;
}
我的/...(...).../
意思是表示您使用您的正则表达式,但是您在与名称本身匹配的模式部分周围添加括号。
然后您可以稍后从感兴趣的“名称”中检索文件名 ( cake_872_trucks
)。
但是,如果可能需要文件名组件来修补不同的(相关的)文件名,则捕获并存储各个组件
my %files;
foreach my $oldfile (@allfiles) {
$oldfile =~ m/(...)(...)(...)/; # your regex, just with capture groups
$files{$2} = [$1, $3]; # add to %files: name => [number, ext]
}
正则表达式仅匹配(为什么@allfiles
用s///
? 更改名称),并捕获。
第一组括号将那个长的前导因子(数字)捕获到 中,第二组括号$1
将名称 ( cake_872_trucks
)捕获到 中,第三组括号$2
具有扩展名 in $3
。
因此,您最终会得到一个带有感兴趣名称的键的哈希,它们的值是带有文件名的所有其他需要组件的数组引用。请根据需要进行调整,因为我不知道该正则表达式的作用并且可能遗漏了某些部分。
现在,一旦您完成,@events
您就可以重建名称
use File::Copy qw(move);
foreach my $name (@events) {
my ($num, $ext) = @{ $files{$name} };
my $file = $num . $name . $ext;
say "Move $file from $orig_dir to $dest_dir";
move("$orig_dir/$file", $dest_dir) or warn "Can't move $file: $!";
}
但是,如果要移动的文件确实来自@allfiles
(如本例中的情况),则使用上面的第一个版本将文件名存储为值%files
,现在检索它们
foreach my $name (@events) {
move ("$orig_dir/$files{$name}", $dest_dir)
or warn "Can't move $file: $!";
}
我使用核心模块File::Copy,而不是向系统发出移动命令。
您还可以通过再次浏览目录来重建名称,现在手头上有感兴趣的名称。但这会非常昂贵,因为您必须尝试匹配@events
目录中读取的每个文件的每个名称(O(mn)复杂度)。
你问的可以用glob完成(并注意File::Glob的版本)
my @files = glob "$dir/*${name}*";
但是你必须为每一个都这样做$name
——这是一种巨大而不必要的资源浪费。
如果那个正则表达式真的必须拼出特定的数字,这里有一种组织它以便于消化(和调试!)的方法:将它分成合理的部分,每个部分都有一个单独的变量。
理想情况下,交替的每一部分都是一个变量
my $p1 = qr/.../;
my $p2 = qr/.../;
...
my $re_alt = join '|', $p1, $p2, ...;
my $re_other = qr/.../;
$var =~ m/^($re_alt)($re_other)(.*)$/; # adjust anchors, captures, etc
qr
运算符在其中构建正则表达式模式。
根据您的实际需要调整那些捕获括号、锚点等。将其分解以便将正则表达式明智地拆分为变量将对可读性和正确性大有帮助。
假设有充分的理由在文件名中寻找这些特定数字,这也是记录任何此类固定因素的好方法。
推荐阅读
- android - 在 intellij 中运行示例 dart 应用程序时发生错误
- azure-functions - Azure Function App 和 Microsoft.TeamFoundationServer.Client Nuget 包在依赖项中的冲突
- mysql - 从 ib_logfile、ibdata 文件中恢复 mysql 数据库
- python - 从 Python 执行插入时,如何调用 SQL Server 函数作为参数
- geolocation - geolite_city_bq_b2 数据集的准确性
- r - 用于查找至少 2 个在 2 个字符串之间匹配的单词的 R 函数(应用于 2 个字符串向量)?
- react-native - 将 react-native-web 添加到现有的 react-native 应用程序时出错
- azure-service-fabric - actor->actor 或 service->actor 调用的底层机制是什么,它们的可靠性如何?
- assembly - CL 比较验证范围不起作用
- amazon-web-services - 使用 AWS Go 开发工具包将消息发布到 SNS