正则表达式比较部分文件名,然后移动到另一个目录perl



我正在编写一个脚本,用于比较目录中未运行的文件与命令中正在运行的文件。我必须使用正则表达式从目录中删除文件名的前半部分,然后正则表达式将文件名从命令中剥离出来,然后将不匹配的名称记录到数组中。

我无法弄清楚的部分是如何将文件名从旧目录移动到新目录中以供将来删除。

为了移动文件,我需要将它们括在通配符中,* 由于文件名和扩展名前面的随机数。 之前和之后的示例文件名:

目录内:

13209811124300209156562070_cake_872_trucks.rts

在命令内:

{"file 872","cake_872_trucks.rts",running}

@events数组中:

cake_872_trucks

我的代码:

#!/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中的原始文件有何关系,因为它们是在移动尝试使用/home/user/RunBackup时从/var/user/data获取的。所以下面的代码片段更通用。

如果移动的正是来自@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]
}

正则表达式仅匹配(为什么要用s///更改@allfiles的名称?(和捕获。

第一组括号将长前导因子(数字(捕获到$1中,第二组括号将名称(cake_872_trucks(捕获到$2中,第三组括号具有扩展名,以$3为单位。

因此,您最终会得到一个带有键的哈希值,这些键是感兴趣的名称,其值是带有文件名所有其他所需组件的 arrayref。 请根据需要进行调整,因为我不知道正则表达式的作用,并且可能遗漏了一些部分。

现在,一旦您经历了@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运算符构建正则表达式模式的地方。

根据您的实际需要调整那些捕获括号、锚点等。将其分解以使正则表达式明智地拆分为变量将大大有助于提高可读性,从而确保正确性。

假设有充分的理由在文件名中查找这些特定数字,这也是记录任何此类固定因素的好方法。

我想你需要这样的东西:

my $path = '/home/user/RunBackup/';
my @files = map {$path."*$_*"} @events;
system(join " ", "mv", @files, "/home/user/RunBackup/files/");

如果有很多文件,您可能需要逐个移动它们:

system(join " ", "mv", $_, "/home/user/RunBackup/files/") for @files;

相关内容

最新更新