[英]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.