Command-Line

重新編號和重命名

  • August 21, 2021

我遇到了需要以以下形式重命名大量文件的情況:

file.csv
file_1.csv
file_2.csv
file_3.csv
file_4.csv
file_5.csv
file_6.csv
file_7.csv
file_8.csv

為了更好地訂購,即:

file_1.csv
file_2.csv
file_3.csv
file_4.csv
file_5.csv
file_6.csv
file_7.csv
file_8.csv
file_9.csv

即,我可以手動重命名第一個文件,但是對於剩餘的“ _#”文件,我需要用+1. 我試著用

rename -n -v 's/_(.*)./.(\1+1)./' 

但得到了

file_(1+1).csv
file_(2+1).csv

等等

請問有什麼簡單的方法可以批量保留“ _#”文件嗎?

PS,最好是

file_01.csv
. . .
file_09.csv
file_10.csv
. . .

如果可能的話。

更新:

感謝cas的回答。因為我會將它們重命名為零填充名稱,所以文件名不會衝突,所以對我來說命令可以簡化為:

touch file.csv file_{1..9}.csv

$ rename -v 's/^(file_)(\d+)(\.csv)$/$1 . (sprintf "%02i", $2 + 1) . $3/e' file_*
file_1.csv renamed as file_02.csv
file_2.csv renamed as file_03.csv
file_3.csv renamed as file_04.csv
file_4.csv renamed as file_05.csv
file_5.csv renamed as file_06.csv
file_6.csv renamed as file_07.csv
file_7.csv renamed as file_08.csv
file_8.csv renamed as file_09.csv
file_9.csv renamed as file_10.csv

注意最後兩個文件名:

file_09.csv
file_10.csv

您需要使用 perl 的/e正則表達式修飾符,使其將操作的右側計算s///為 perl 表達式。

您還需要以相反的數字順序對文件名進行排序,以便在編號較低的文件名之前重命名編號最高的文件名(否則會出現文件名衝突 - 預設情況下,除非您使用-f強制它,否則rename將拒絕覆蓋現有文件)。為此,我將使用 GNU findwith-print0和 GNU sortwith-z進行以 NUL 結尾的輸入,-r-V使用反向版本(即“自然”)排序。 -t _-k 2選項也用於從第二個欄位排序。

rename 的-d選項用於使其僅重命名路徑名的文件名部分,並-0使其在標準輸入上採用 NUL 分隔的文件列表。

例如

$ touch file.csv file_{1..8}.csv
$ find . -name 'file_*.csv' -print0 |
   sort -z -t _ -k2 -r -V |
   rename -d -0 's/^(file_)(\d+)(\.csv)$/$1 . ($2 + 1) . $3/e'
$ mv file.csv file_1.csv
$ ls -l
total 5
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_1.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_2.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_3.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_4.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_5.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_6.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_7.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_8.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_9.csv

這可以稍微簡化一點,但我已經讓正則表達式明確地查找和擷取file_一個或多個數字和.csv副檔名,以避免任何不應該重命名文件的可能性。

要使文件編號補零,您可以使用該sprintf功能。例如

... | rename -0 -d -v 's/^(file_)(\d+)(\.csv)$/$1 . (sprintf "%02i", $2 + 1) . $3/e'
Reading filenames from file handle (GLOB(0x555555905960))
./file_8.csv renamed as ./file_09.csv
./file_7.csv renamed as ./file_08.csv
./file_6.csv renamed as ./file_07.csv
./file_5.csv renamed as ./file_06.csv
./file_4.csv renamed as ./file_05.csv
./file_3.csv renamed as ./file_04.csv
./file_2.csv renamed as ./file_03.csv
./file_1.csv renamed as ./file_02.csv

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