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

时间:2018-10-22 01:39:11

标签: file perl filesystems move

我正在研究一个脚本,用于比较目录中未运行的文件和命令中正在运行的文件。我必须使用Regex从目录中删除文件名的前半部分,然后使用regex从命令中删除文件名,然后再将不匹配的名称记录到数组中。

我不知道的部分是如何将文件名从旧目录移到新目录中以供将来删除。

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

在目录内:

13209811124300209156562070_cake_872_trucks.rts

在命令内:

{“文件872”,“ cake_872_trucks.rts”,正在运行}

@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 

2 个答案:

答案 0 :(得分:1)

使用正则表达式解析文件名后,就没有理由无法捕获所有部分,以便以后可以重新构造文件名中所需的部分。

我认为过长(且不完整)的正则表达式可以达到预期的目的。

我不确定要移动的文件与@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中,第三组具有扩展名,在$3中。

因此,您最终得到的哈希是带有相关名称的键的键,它们的值是具有文件名所有其他所需组件的arrayrefs。请调整一下,因为我不知道该正则表达式会做什么,并且可能遗漏了某些部分。

现在,一旦您通过@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,而不是使用move命令进入系统。

还可以通过再次浏览目录来重新构建名称,现在手头有感兴趣的名称。但这会非常昂贵,因为您必须为目录中读取的每个文件尝试匹配@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 operator构建正则表达式模式的地方。

根据您的实际需要调整捕获括号,锚点等的内容。对其进行分解,以便将正则表达式合理地拆分为变量,将大大提高可读性,从而确保正确性。

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

答案 1 :(得分:0)

我想您需要这样的东西:

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;