perl rename:在子目录中的一组文件名前面添加一些内容

perl rename:在子目录中的一组文件名前面添加一些内容

虽然perlrename工具已成为我日常工作的宝贵伴侣,但仍然存在一些怪癖,使工作变得更加困难 - 特别是当文件被不是在当前工作目录中。

假设有很多发票,并且我们知道来自 customer1 的所有发票都已分配给一个帐户。因此,为了使以后的脚本处理更容易,我们希望assi_在前面添加“已分配”。

例如:

/home/user/bizz/invoices $ ls -1 t1/inv*

t1/inv_customer1_20130506.txt
t1/inv_customer1_20130823.txt
t1/inv_customer1_20130930.txt
t1/inv_customer2_20131207.txt
t1/inv_customer2_20131113.txt

现在看看会发生什么:

/home/user/bizz/invoices $ rename 's/^/assi_/' t1/inv_customer1*

Can't rename t1/inv_customer1_20130506.txt assi_t1/inv_customer1_20130506.txt: No such file or directory
(etc.)

呵呵。rename 已选择了整个路径用于添加assi_到文件之前,而不仅仅是文件。所以难怪找不到inv_customer1_20130506.txt在不存在的目录“assi_t1”。

那么如何才能rename教导将正则表达式仅应用于文件名呢?

注意:
1. 我并不总是想cd进入子目录。2
. 如果可能的话,我会避免使用循环以及find

答案1

rename以这种方式工作是因为它可以在目录之间移动文件。与 一样mv,它作用于整个路径,而不仅仅是最后一个组件。

如果您只想修改最后一个组件,则可以将正则表达式锚定在(\A|?<=/),并确保它不匹配任何/且仅匹配最后一个/

rename 's~(\A|?<=/)(?=[^/]*)\z~assi_~' t1/inv_customer1*

另一种方法是首先分割文件名。

rename 's~(.*/)~~s; my $d = $1; s/\A/assi_/; $_ = "$d$_"' t1/inv_customer1*

您也可以使用该File::Spec模块。这具有处理非 Unix 路径的优点。

rename 'use File::Spec::Functions; my ($v,$d,$f) = splitpath($_); $f =~ s/\A/assi_/; $_ = catpath($v,$d,$f)' t1/inv_customer1*

相关内容