Regular-Expression

perl rename:在跨子目錄的一組文件名前添加一些東西

  • November 9, 2014

儘管perl’srename工具已成為我日常工作的寶貴伴侶,但仍有一些怪癖使工作變得更加困難——尤其是當文件不在目前工作目錄中時。

假設有很多發票,並且我們知道來自 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_,而不僅僅是文件。所以難怪它在不存在的目錄“assi_t1”中找不到inv_customer1_20130506.txt 。

那麼如何rename教只將正則表達式應用於文件名呢?

注意事項:

  1. 我並不總是想去cd子目錄。

  2. 如果可能的話,我會避免使用循環find

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*

引用自:https://unix.stackexchange.com/questions/166859