Когда вы анализируете имена файлов с помощью регулярных выражений, нет никаких причин не иметь возможности захватывать все части, чтобы впоследствии можно было восстановить необходимые части имени файла.
Я предполагаю, что это слишком долго (и не полностью)regex делает то, для чего предназначен.
Я не уверен, как перемещаемые файлы относятся к исходным файлам в @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: $!";
}
Iиспользуйте модуль ядра 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
создает шаблон регулярного выражения.
Отрегулируйте эти захватывающие скобки,якоря и т. д. для ваших реальных потребностей.Разбив его так, чтобы регулярное выражение было разумно разбито на переменные, будет иметь большое значение для удобочитаемости и, следовательно, правильности.
Предполагая, что есть веская причина для поиска этих конкретных чисел в именах файлов, это также хорошоспособ документировать любые такие фиксированные факторы.