我在 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_file1
和apre_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
,在其他系统上它可能被称为prename
或perl-rename
),然后你就可以这样做(虽然这不是不区分大小写,但它只查找包含 的文件pre_
):
rename -n 's/.*?pre_//si' ./*
导致只打印它会做什么,而不实际重命名-n
。rename
一旦确定重命名按预期工作,请再次运行该命令,而无需-n
实际重命名文件。
外壳经过这里全部(非隐藏)文件并将rename
忽略代码未更改rename
名称的文件。perl
您还可以告诉 shell 仅通过in 、 in传递包含pre_
不区分大小写的文件名,在、或或 use中全局设置选项。./~(i)*pre_*
ksh93
./(#i)*pre_*
zsh -o extendedglob
nocaseglob
bash
zsh
yash
./*[pP][rR][eE]_*
答案2
您需要的工具已经存在rename
(也取决于您的发行版perl-rename
或prename
)
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
(为了冗长)所以实际的重命名将会发生。