2014-01-26 122 views
7

我只學習使用REGEX,AWK和SED。我目前有一組我想要重命名的文件 - 它們都位於一個目錄中。AWK,SED,REGEX重命名文件

的命名模式是一致的,但我想重新安排的文件名,這裏的格式是:

01._HORRIBLE_HISTORIES_S2.mp4 
02._HORRIBLE_HISTORIES_S2.mp4 

我想他們重命名爲HORRIBLE_HISTORIES_s01e01.mp4 - 其中E01是收集從第一列開始。我知道我想從第一列抓取「01」,將它填入一個變量中,然後將它粘貼到每個文件名中的S2之後,同時我想將它從文件名的開頭與「」一起移除。 _「,另外我想將」S2「更改爲」s02「。

如果有人會這麼友善,你能幫我用awk/sed寫一些東西,並解釋一下程序,我可以從中學習嗎?

回答

6
for f in *.mp4; do 
    echo mv "$f" \ 
    "$(awk -F '[._]' '{ si = sprintf("%02s", substr($5,2)); 
          print $3 "_" $4 "_s" si "e" $1 "." $6 }' <<<"$f")" 
done 
  • 遍歷所有*.mp4文件。
  • 將每個名稱都重命名爲awk命令的結果,通過命令替換($(...))提供。
  • awk命令將輸入​​文件名拆分爲.或「_」(使第一個令牌可用爲$1,第二個令牌爲$2,...)。首先,將「_S {number}」中的數字左填充到2位數,其中0(即0僅在數字不具有2位數字時被預置)並存儲在變量si(季節指數);如果始終可以加上0,那麼awk「程序」可以簡化爲:{ print $3 "_" $4 "_s0" substr($5,2) "e" $1 "." $6 }
  • 結果與剩餘的標記一起重新排列以形成所需的文件名。

mvecho,讓您安全地預覽生成的命令 - 刪除它來執行實際的重命名。

替代

for f in *.mp4; do 
    [[ $f =~ ^([0-9]+)\._([^.]+)_S([^.]+)\.(.+)$ ]] 
    echo mv "$f" \ 
"${BASH_REMATCH[2]}_s0${BASH_REMATCH[3]}e${BASH_REMATCH[1]}.${BASH_REMATCH[4]}" 
done 
  • 用途bash的正則表達式匹配操作,=~,用捕獲基團(在(...)子串)來匹配每個文件名:使用正則表達式的純bash溶液並提取感興趣的子串。
  • 匹配結果存儲在特殊數組變量$BASH_REMATCH中,其中元素0包含整個匹配,1包含與第一個捕獲組相匹配的內容,第二個爲2,依此類推。
  • mv命令的目標參數然後組裝捕獲組中的期望的順序相匹配;請注意,在這種情況下,爲了簡單起見,我已無條件地創建了s{number}的零填充 - 僅將0作爲前綴。

與上面一樣,您需要在mv之前刪除echo以執行實際重命名。

0

將文件名字符串變爲文本文件,然後使用循環和awk重命名文件。

while read oldname; do 
    newname=$(awk -F'.' '{ print substr($2, 2) "_e" $1 "." $3 }' <<< ${oldname} | \ 
     awk -F'_' '{ print $1 "_s0" substr($2, 2) $3 }'); 
    mv ${oldname} ${newname}; 
done<input.txt 
1

您可以用純幾乎bash(與variable expansion)做到這一點:

for f in in *mp4 ; do 
    newfilename="${f:5:20}_s01e${f:1:2}.mp4" 
    echo mv $f $newfilename 
done 

如果此命令套房輸出你的需求,你可能會從週期的echo或者更簡單(如果您的最後一個命令是以上)問題:!! | bash

8

根據模式重命名多個文件的常用方法是使用Perl命令rename。它使用Perl正則表達式,功能非常強大。使用-n -v測試模式而不觸及文件:

$ rename -n -v 's/^(\d+)._(.+)_S2\.mp4/$2_s02e$1.mp4/' *.mp4 
01._HORRIBLE_HISTORIES_S2.mp4 renamed as HORRIBLE_HISTORIES_s02e01.mp4 
02._HORRIBLE_HISTORIES_S2.mp4 renamed as HORRIBLE_HISTORIES_s02e02.mp4 

使用括號來捕捉字符串到變量$1(第一捕獲),$2(第二捕獲)等:在開始

  • ^(\d+)捕獲數字文件名(換成$1)
  • ._(.+)_S2\.mp4捕獲.__S2.mp4之間的所有內容(進入$2
  • $2_s02e$1.mp4組裝與捕獲的數據的新的文件名,只要你想它

當你對結果滿意,請從命令-n,它會重新命名所有的文件真實。

rename往往是在Linux(包util-linux)默認情況下可用。 SO上有一個similar discussion,其中有關於查找/安裝正確命令的更多詳細信息。

0

如果你願意使用gawk,正則表達式匹配真正派上用場。我發現這種基於管道的解決方案比擔心循環構造更好一點。

ls -1 | \ 
    gawk 'match($0, /.../, a) { printf ... | "sh" } \ 
    END { close("sh") }' 

爲了便於閱讀,我取代了正則表達式,並與橢圓的mv命令。

  • 第1行列出了當前目錄中的所有文件名,每行一行,以及管道連接到gawk命令。
  • 線2運行的正則表達式匹配,分配捕獲的基團與數組變量a。該動作將其轉換爲我們想要的命令,其中printf本身通過管道連接到sh執行。
  • 第3行關閉了在我們開始將事物管道輸送給它時隱式打開的外殼。

那麼你只需填寫你的正則表達式和命令語法(從mklement0借用)。例如(LIVE CODE警告):

ls -1 | \ 
    gawk 'match($0, /^([0-9]+)\._([^.]+)_S([^.]+)\.(.+)$/, a) { printf "mv %s %s_s0%se%s.%s\n",a[0],a[2],a[3],a[1],a[4] | "sh" } \ 
    END { close("sh") }' 

要預覽命令(作爲應)可以簡單地從第二行刪除| "sh"