【问题标题】:AWK, SED, REGEX to rename filesAWK、SED、REGEX 重命名文件
【发布时间】:2014-02-17 00:50:00
【问题描述】:

我只是在学习使用 REGEX、AWK 和 SED。我目前有一组要重命名的文件 - 它们都位于一个目录中。

命名模式是一致的,但我想重新排列文件名,格式如下:

01._HORRIBLE_HISTORIES_S2.mp4
02._HORRIBLE_HISTORIES_S2.mp4

我想将它们重命名为 HORRIBLE_HISTORIES_s01e01.mp4 - 其中 e01 是从第一列中收集的。我知道我想从第一列中获取“01”,将其填充到一个变量中,然后将其粘贴在每个文件名中的 S2 之后,同时我想从文件名的开头将其与“. _”,另外我想把“S2”改成“s02”。

如果有人这么好心,你能帮我用 awk/sed 写一些东西并解释一下过程,我可以从中学习吗?

【问题讨论】:

    标签: regex sed awk filenames renaming


    【解决方案1】:

    使用 AWK。用第一部分、第二部分和第四部分重命名文件

    ls | while read file; do newfile=`echo $file | awk -F . '{print $1 "." $2 "." $4}'`; echo $newfile;  mv $file $newfile; done;
    

    【讨论】:

      【解决方案2】:

      你可以用几乎纯粹的bashvariable expansion)来做到这一点:

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

      如果此命令的输出符合您的需要,您可以从循环中删除 echo,或者更简单(如果您的最后一个命令是上述)问题:!! | bash

      【讨论】:

      • 我认为这仅适用于固定大小的字符串。您将如何用任意大小的另一个扩展替换一个扩展?
      【解决方案3】:
      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}”中的数字用0 左填充为2 位数字(即,0 仅在该数字还没有2 位数字的情况下添加)并存储在变量si(季节指数);如果可以始终添加 0,则 awk“程序”可以简化为:{ 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 的正则表达式匹配运算符 =~ 和捕获组((...) 中的子字符串)来匹配每个文件名并提取感兴趣的子字符串。
      • 匹配结果存储在特殊数组变量$BASH_REMATCH中,元素0包含整个匹配,1包含匹配第一个捕获组的内容,2第二个,依此类推。李>
      • mv 命令的目标参数然后按所需顺序组装捕获组匹配项;请注意,在这种情况下,为简单起见,我将 s{number} 的零填充设置为无条件 - 0 只是在前面添加。

      如上,您需要在mv之前删除echo才能执行实际重命名。

      【讨论】:

        【解决方案4】:

        如果您愿意使用gawk,那么正则表达式匹配真的会派上用场。我发现这种基于管道的解决方案比担心循环结构要好一些。

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

        为了便于阅读,我已将正则表达式和 mv 命令替换为省略号。

        • 第 1 行列出了当前目录中的所有文件名,每行一行并将其传递给 gawk 命令。
        • 第 2 行运行正则表达式匹配,将捕获的组分配给数组变量 a。该操作将其转换为带有printf 的所需命令,该命令本身通过管道传送到sh 以执行。
        • 第 3 行关闭了在我们开始向其传输内容时隐式打开的 shell。

        那么你只需填写你的正则表达式和命令语法(借用mklement0)。例如(实时代码警告):

        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"

        【讨论】:

          【解决方案5】:

          根据模式重命名多个文件的常用方法是使用 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,其中包含有关查找/安装正确命令的更多详细信息。

          【讨论】:

            【解决方案6】:

            将文件名字符串变成文本文件,然后使用循环和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
            

            【讨论】:

              猜你喜欢
              • 2021-05-26
              • 2019-10-05
              • 2019-01-09
              • 1970-01-01
              • 2011-07-31
              • 2011-01-23
              • 2011-08-06
              • 2013-06-12
              • 2021-06-04
              相关资源
              最近更新 更多