Bash

如何通過在文件名中的任何位置填充數字來重命名文件?

  • June 8, 2020

我在包含影片文件的 Deepin(基於 Debian)系統上有一個目錄,如下所示:

SL Benfica - Match 1 vs FC Porto.mp4
SL Benfica - Match 2 vs FC Porto.mp4
...
SL Benfica - Match 20 vs FC Porto.mp4
...
SL Benfica - Match 100 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4

我想在中間的數字之前添加零,以便它們按如下方式排序

SL Benfica - Match 001 vs FC Porto.mp4
SL Benfica - Match 002 vs FC Porto.mp4
...
SL Benfica - Match 020 vs FC Porto.mp4
...
SL Benfica - Match 100 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4

我正在尋找一個不依賴於模式的通用命令。只需搜尋 5 和 20 之類的數字,並將它們更改為 005 和 020,在文件名的任何位置,甚至在文件名的末尾或開頭。

您可以使用perl-rename(應該可以sudo apt install rename在基於 Debian 的系統上安裝)。使用這些文件作為輸入:

$ ls -1
'anotherFile.m4a'    
'file 1 with 12 many 100 numbers 3.mp4'
'SL Benfica - Match 101 vs FC Porto.mp4'
'SL Benfica - Match 20 vs FC Porto.mp4'
'SL Benfica - Match 2 vs FC Porto.mp4'

你可以執行:

rename 's/(\d+)(?=.*\.)/sprintf("%03d",$1)/eg' *

這會將它們重命名為:

'anotherFile.m4a'
'file 001 with 012 many 100 numbers 003.mp4'
'SL Benfica - Match 002 vs FC Porto.mp4'
'SL Benfica - Match 020 vs FC Porto.mp4'
'SL Benfica - Match 101 vs FC Porto.mp4'

請注意如何100保持不變,其餘部分被填充。還要注意 4 in.m4amp4沒有受到影響。

重要:在實際重命名文件之前先執行命令,-n看看會發生什麼:

rename -n 's/(\d+)(?=.*\.)/sprintf("%03d",$1)/eg' *

正則表達式查找\d+在至少一位.( ?=.*\.) 之前的一位或多位數字 ( ) 的延伸。這是為了避免更改在擴展程序中找到的號碼。但是,如果您的文件名沒有副檔名,這將不起作用。如果您有這樣的文件,請使用它來填充所有數字:

rename 's/(\d+)/sprintf("%03d",$1)/eg' *

s/old/new/替換運算符,它將替換oldnew。在這裡,因為(\d+)括號中的是,所以匹配的內容將被擷取,然後將$1在替換的右側可用。因此,我們用自己填充的 0 替換數字(sprintf("%03d", $number)將列印$number用 0 填充,直到其長度為 3)。最後,該標誌e允許我們使用表達式(此處為sprintfg並使替換全域,用於輸入行(文件名)上的所有匹配項。

請注意,如果您的數字已經被 0 填充且超過 3 個 0,這會將其修剪為 3-0 填充。所以file 00000001.mp3會變成file 001.mp3

zsh

autoload -Uz zmv # best in ~/.zshrc
zmv -n '(*).mp4' '${1//(#m)<->/${(l[3][0])MATCH}}.mp4'

-n如果滿意,請刪除(試執行)。

  • zmv根據 zsh glob 模式重命名文件。這裡(*).mp4匹配以 結尾的文件名,.mp4之前的部分.mp4擷取,因此可以用作$1替換。
  • ${1//pattern/replacement}: ksh 運算符對參數(此處$1)擴展執行替換。
  • pattern(#m)<->一個 zshextendedglob模式。使匹配的文本在替換(#m)中可用,這是數字匹配運算符的最簡單形式,匹配任何 1 個或多個十進制數字的序列。與 相同。$MATCH``<->``<x-y>``[0-9]##
  • ${(l[3][0])param}使用l[length][padstring]參數擴展標誌將$MATCH0 的擴展左填充到長度 3(請注意,它也會將數字截斷為長度 3)。

避免截斷是可能的,儘管它變得有點複雜:

zmv -n '(*).mp4' '${1//(#m)<->/${(l[$#MATCH > 3 ? $#MATCH : 3][0])MATCH}}.mp4'

我們不是填充+截斷到長度 3,而是填充+截斷到最大長度為 3 和要填充的字元串的長度。或者,您可以使用max()autoloadable 函式中的數學zmathfunc函式:

autoload -Uz zmv zmathfunc; zmathfunc
zmv -n '(*).mp4' '${1//(#m)<->/${(l[max(3, $#MATCH)][0])MATCH}}.mp4'

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