use*_*123 8 regex awk filenames sed renaming
我只是学习使用REGEX,AWK和SED.我目前有一组我想要重命名的文件 - 它们都位于一个目录中.
命名模式是一致的,但我想重新安排文件名,这里是格式:
01._HORRIBLE_HISTORIES_S2.mp4
02._HORRIBLE_HISTORIES_S2.mp4
Run Code Online (Sandbox Code Playgroud)
我想将它们重命名为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
Run Code Online (Sandbox Code Playgroud)
*.mp4文件.awk命令的结果,通过命令substitution($(...))提供.awk命令将输入文件名拆分为标记.或"_"(使第一个标记可用$1,第二个标记为$2......).0(即,0如果数字不具有2位数,则仅预设a )并存储在变量si(季节索引)中; 如果总是可以预先添加0,那么awk"程序"可以简化为:{ print $3 "_" $4 "_s0" substr($5,2) "e" $1 "." $6 }请注意echo之前mv允许您安全地预览生成的命令 - 将其删除以执行实际重命名.
替代方案: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
Run Code Online (Sandbox Code Playgroud)
=~使用捕获组(子字符串(...))匹配每个文件名并提取感兴趣的子字符串.$BASH_REMATCH,其中元素0包含整个匹配,1包含与第一个捕获组匹配的内容,2第二个匹配,依此类推.mv命令的target参数按所需顺序组装捕获组匹配; 请注意,在这种情况下,为简单起见,我做了s{number}无条件的零填充- 一个0简单的前置.如上所述,您需要echo在mv执行实际重命名之前删除.
根据模式重命名多个文件的常用方法是使用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
Run Code Online (Sandbox Code Playgroud)
使用括号将字符串捕获到变量$1(第一次捕获),$2(第二次捕获)等:
^(\d+) 在文件名开头捕获数字(进入 $1)._(.+)_S2\.mp4捕捉到(._和)之间的所有内容_S2.mp4$2$2_s02e$1.mp4 根据需要使用捕获的数据组合新文件名如果您对结果感到满意,请-n从命令中删除它,并将所有文件重命名为real.
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
Run Code Online (Sandbox Code Playgroud)
如果此命令的输出满足您的需要,您可以echo从循环中删除,或者更简单地(如果您的最后一个命令是上述)问题:!! | bash