我希望仅批量重命名当前目录中的文件,并从文件名末尾删除某些字符串。
样品:
foo-bar-(ab-4529111094).txt
foo-bar-foo-bar-(ab-189534).txt
foo-bar-foo-bar-bar-(ab-24937932201).txt
输出应如下所示:
foo-bar.txt
foo-bar-foo-bar.txt
foo-bar-foo-bar-bar.txt
我想删除每个文件名末尾的字符串-(ab-2492201)
知道数字的长度会有所不同。
Perl正则表达式比模块更受欢迎,并且不使用任何实用程序,因此非常喜欢使用bash oneliner命令。
如何在Linux上的Perl和Bash Shell中实现这一点?有兴趣了解这两种解决方案。
答案 0 :(得分:5)
尝试:
$ rename 's/-\(ab-\d+\)(?=\.txt$)//' *.txt
用Perl编写了一个rename
命令。它的第一个参数是描述如何转换文件名的Perl代码。您可以在自己的Perl程序或单行程序中使用相同的s///
命令。
如果不起作用,请尝试prename
而不是rename
;在某些系统上安装了一个不同的,基于非Perl的rename
命令,在这种情况下,可以将Perl命令称为prename
。
答案 1 :(得分:4)
在bash中,您可以编写如下内容:
for file in *-\(ab-[0-9]*\)*; do
newfile="${file/-(ab-[0-9]*)/}"
mv "$file" "$newfile"
done
答案 2 :(得分:2)
当您在当前目录下说时,您是指 in 当前目录,还是当前目录及其后代中的任何位置?
File::Find
是一种简单的方法,它是一个核心模块,因此不需要安装。像这样:
use strict;
use warnings;
use autodie;
use File::Find;
find(\&rename, '.');
sub rename {
return unless -f;
my $newname = $_;
return unless $newname =~ s/-\(ab-[0-9]+\)(\.txt)$/$1/i;
print "rename $_, $newname\n";
}
<强>更新强>
此程序将仅在当前目录中重命名具有给定文件名模式的所有文件。
请注意,初始open
循环仅用于创建用于重命名的示例文件。
use strict;
use warnings;
use autodie;
open my $fh, '>', $_ for qw(
foo-bar-(ab-4529111094).txt
foo-bar-foo-bar-(ab-189534).txt
foo-bar-foo-bar-bar-(ab-24937932201).txt
);
for (glob '*.txt') {
next unless -f;
my $newname = $_;
next unless $newname =~ s/-\(ab-[0-9]+\)(\.txt)$/$1/i;
print "rename $_, $newname\n";
rename $_, $newname;
}
<强>输出强>
rename foo-bar-(ab-4529111094).txt, foo-bar.txt
rename foo-bar-foo-bar-(ab-189534).txt, foo-bar-foo-bar.txt
rename foo-bar-foo-bar-bar-(ab-24937932201).txt, foo-bar-foo-bar-bar.txt
答案 3 :(得分:1)
更简单,更短(更好?:))rename
正则表达式:
rename 's@-\(.*?\)@@' foo*.txt
答案 4 :(得分:1)
检查一下:
ls -1 | nawk '/foo-bar-/{old=$0;gsub(/-\(.*\)/,"",$0);system("mv \""old"\" "$0)}'
> ls -1 foo*
foo-bar-(ab-4529111094).txt
foo-bar-foo-bar-(ab-189534).txt
foo-bar-foo-bar-bar-(ab-24937932201).txt
> ls -1 | nawk '/foo-bar-/{old=$0;gsub(/-\(.*\)/,"",$0);system("mv \""old"\" "$0)}'
> ls -1 foo*
foo-bar-foo-bar-bar.txt
foo-bar-foo-bar.txt
foo-bar.txt
>
有关详细说明,请查看here
答案 5 :(得分:0)
通过find
,perl
和xargs
,您可以使用这种单线纸
find . -type f | perl -pe 'print $_; s/input/output/' | xargs -n2 mv
不调用mv
的结果应该只是
OldName NewName
OldName NewName
OldName NewName
find . -type f
输出文件路径(或文件名...您在这里控制正则表达式要处理的内容!)-p
打印正则表达式要处理的文件路径,-e
执行内联脚本print $_
首先打印原始文件名(独立于-p
)-n2
每行打印两个元素mv
获取上一行的输入答案 6 :(得分:0)
仅使用perl的另一种方法:
perl -E'for (<*.*>){ ($new = $_) =~ s/(^.+?)(-\(.+)(\..*$)/$1$3/; say $_." -> ".$new}'
({say ...
非常适合测试,只需将其替换为rename $_,$new
或rename($_,$new)
)
<*.*>
读取当前目录中的每个文件($new = $_) =~
将以下替换保存在$new
中,并使$_
保持不变(^.+?)
将此匹配项从开始一直保存到$ 1,并将非贪心匹配项保存到... (-\(.+)
序列“-(...任何...”。(此匹配项将保存在$ 2中)(\..*$)
保存最后一个“”中的所有内容。 (句点)在行尾($)之前,直到并包括行尾->进入$ 3 $1$3
生成的字符串替换匹配项(您也可以使用perl -E'for (</tmp/my/directory/*.*>){ .....