Regular-Expression
perl rename:在跨子目錄的一組文件名前添加一些東西
儘管
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
教只將正則表達式應用於文件名呢?注意事項:
我並不總是想去
cd
子目錄。如果可能的話,我會避免使用循環
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*