使用 perl 脚本重命名 Linux 中的文件

使用 perl 脚本重命名 Linux 中的文件

我在 Linux 机器上有一组带有前缀的文件,比如“pre_”,我只想通过删除它来重命名所有这些文件。这是我编写的 perl 代码,它不会引发任何错误,但工作尚未完成。

#!/usr/bin/perl -w
my @files = `ls -1 | grep -i \"pre_.*\"`;
foreach $file ( @files )
{
  my @names = split(/pre_/, $file);
  my $var1 = $names[1];
  'mv "$file" "$var1"';
}

答案1

你没有执行任何事情。当您将某些内容放在单引号 ( '') 中时,这只是一个字符串,因此'mv "$file" "$var1"'不是命令,它是一个字符串并且不执行任何操作。字符串本身就是一个真实的陈述。为了执行该命令,您需要使用:

system "mv", "--", $file, $var1;

(不是 system("mv '$file' '$var1'")这会引入命令注入漏洞)。

但没有必要,perl有一个rename()功能,所以你可以这样做:

rename($file, $var1)

接下来,您确实不应该解析 的输出ls,即一个非常糟糕的主意而且很脆弱。在 Perl(或任何其他编程语言)中也完全没有必要。如果你想匹配当前目录中包含该字符串的所有文件pre_(这就是你grep所做的——你不需要grep,顺便说一句,你可以只使用ls -d -- *pre_*),你可以glob()这样使用:

my @files = glob("*pre_*");

因此,将所有这些放在一起,这就是您想要做的:

#!/usr/bin/perl -w
use File::Glob qw(:globally :nocase);
my @files = glob("*pre_*");
foreach $file ( @files )
{
  my @names = split(/pre_/i, $file);
  rename($file, $names[1]);
}

但这确实不是一个好主意。如果您有两个具有相同前缀(例如pre_file1apre_file1)的文件,则第一个文件将被第二个文件覆盖,因为在本示例中,两个文件都将被重命名为,file1因为您的命令将删除pre_其之前的所有内容。因此,您可以添加警告并跳过这些文件:

#!/usr/bin/perl -w
use File::Glob qw(:globally :nocase);

my @files = glob("*pre_*");
foreach $file ( @files )
{
  my @names = split(/pre_/i, $file);
  if (-e $names[1]) {
    warn "Warning: Not renaming '$file' to '$names[1]' " .
        "because '$names[1]' exists.\n";
    next;
  }
  rename($file, $names[1]) or
    warn "rename '$file': $!\n";
}

当然,这一切都是在重新发明轮子。你可以直接安装perl-rename(在 Debian、Ubuntu 等上运行apt install rename,在其他系统上它可能被称为prenameperl-rename),然后你就可以这样做(虽然这不是不区分大小写,但它只查找包含 的文件pre_):

rename -n 's/.*?pre_//si' ./*

导致只打印它会做什么,而不实际重命名-nrename一旦确定重命名按预期工作,请再次运行该命令,而无需-n实际重命名文件。

外壳经过这里全部(非隐藏)文件并将rename忽略代码未更改rename名称的文件。perl您还可以告诉 shell 仅通过in 、 in传递包含pre_不区分大小写的文件名,在、或或 use中全局设置选项。./~(i)*pre_*ksh93./(#i)*pre_*zsh -o extendedglobnocaseglobbashzshyash./*[pP][rR][eE]_*

答案2

您需要的工具已经存在rename(也取决于您的发行版perl-renameprename

rename 's/^pre_//' file1 file2 ...

用于-n试运行和-v列出重命名。

rename注意:不要与工作方式不同的命令混淆util-linux

答案3

...还有其他重命名替代方案(而不是“重新发明轮子”) 是 ...

使用mmv像这样:

$ mmv -n '*_*.ext' '#2.ext'
pre_file_number1.ext -> file_number1.ext
pre_file_number2.ext -> file_number2.ext
pre_file_number3.ext -> file_number3.ext
pre_file_number4.ext -> file_number4.ext

或者在 Z Shell 中(zsh) 使用其内置函数zmv像这样:

% autoload zmv
% zmv -n '*.ext' '${f#*_}' 
mv -- pre_file_number1.ext file_number1.ext
mv -- pre_file_number2.ext file_number2.ext
mv -- pre_file_number3.ext file_number3.ext
mv -- pre_file_number4.ext file_number4.ext

注意:-n在上述两种情况下都是为了安全试运行...当对输出感到满意时,将其删除或替换为-v(为了冗长)所以实际的重命名将会发生。

相关内容