[英]AWK, SED, REGEX to rename files
我只是在學習使用REGEX,AWK和SED。 我目前有一組要重命名的文件-它們都位於一個目錄中。
命名模式是一致的,但是我想重新排列文件名,這里是格式:
01._HORRIBLE_HISTORIES_S2.mp4
02._HORRIBLE_HISTORIES_S2.mp4
我想將它們重命名為HORRIBLE_HISTORIES_s01e01.mp4-從第一列中收集e01。 我知道我想從第一列中獲取“ 01”,將其填充到變量中,然后將其粘貼到每個文件名的S2之后,與此同時,我想從文件名的開頭將其與“一起刪除”。 _”,此外,我想將“ S2”更改為“ s02”。
如果有人那么善良,您能幫我用awk / sed編寫一些東西並解釋該過程,以便我可以從中學習嗎?
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
,...)。 0
左填充到2位數字(即,僅當數字還沒有2位數字時才添加0
)並存儲在變量si
(季節索引)中; 如果可以始終始終添加0
,則可以將awk“程序”簡化為: { print $3 "_" $4 "_s0" substr($5,2) "e" $1 "." $6 }
{ print $3 "_" $4 "_s0" substr($5,2) "e" $1 "." $6 }
在mv
之前記下echo
,以使您可以安全地預覽生成的命令-刪除它以執行實際的重命名。
替代方案 :使用正則表達式的純bash
解決方案:
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_REMATCH
,與元件0
包含整個比賽, 1
含有什么第一捕獲組,火柴2
第二,等等。 mv
命令的目標參數按所需順序組合捕獲組匹配項。 請注意,在這種情況下,為簡單起見,我將s{number}
的零填充設為無條件-只是在前面加上了0
。 如上所述,您需要在mv
之前刪除echo
以執行實際的重命名。
根據模式重命名多個文件的常用方法是使用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上也有類似的討論 ,其中包含有關查找/安裝正確命令的更多詳細信息。
您可以使用幾乎純bash
(具有可變的擴展 )來做到這一點:
for f in *mp4 ; do
newfilename="${f:5:20}_s01e${f:1:2}.mp4"
echo mv $f $newfilename
done
如果此命令的輸出適合您的需要,則可以從循環中刪除echo
,或者更簡單地(如果您的最后一個命令是上述命令)發出以下問題: !! | bash
!! | bash
使文件名字符串成為文本文件,然后使用loop和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
如果您願意使用gawk
,則正則表達式匹配確實非常有用。 我發現這種基於管道的解決方案比擔心循環構造要好得多。
ls -1 | \
gawk 'match($0, /.../, a) { printf ... | "sh" } \
END { close("sh") }'
為了便於閱讀,我用省略號替換了regex和mv
命令。
a
。 該動作使用printf
其轉換為我們所需的命令,該命令本身通過管道傳遞給sh
以執行。 因此,您只需填寫正則表達式和命令語法(從mklement0借用)。 例如( LIVE CODE WARNING ):
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"
第二行的| "sh"
。
使用AWK。 用第一部分,第二部分和第四部分重命名文件
ls | while read file; do newfile=`echo $file | awk -F . '{print $1 "." $2 "." $4}'`; echo $newfile; mv $file $newfile; done;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.