AWK、SED、REGEX重命名文件

AWK、SED、REGEX重命名文件,regex,sed,awk,filenames,renaming,Regex,Sed,Awk,Filenames,Renaming,我只是在学习使用正则表达式、AWK和SED。我目前有一组我想重命名的文件-它们都位于一个目录中 命名模式是一致的,但我想重新排列文件名,格式如下: 01._HORRIBLE_HISTORIES_S2.mp4 02._HORRIBLE_HISTORIES_S2.mp4 我想将它们重命名为Thorbit_HISTORIES_s01e01.mp4,其中e01是从第一列中收集的。我知道我想从第一列抓取“01”,将其填入一个变量中,然后将其粘贴到每个文件名的S2之后,同时我想将其从文件名开头连同“.”一

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

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

01._HORRIBLE_HISTORIES_S2.mp4
02._HORRIBLE_HISTORIES_S2.mp4
我想将它们重命名为Thorbit_HISTORIES_s01e01.mp4,其中e01是从第一列中收集的。我知道我想从第一列抓取“01”,将其填入一个变量中,然后将其粘贴到每个文件名的S2之后,同时我想将其从文件名开头连同“.”一起删除,此外,我还想将“S2”更改为“s02”


如果有人愿意的话,你能帮我用awk/sed写些东西,并解释一下这个过程,让我从中学习吗?

将文件名字符串转换成文本文件,然后使用循环和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
读取oldname时
;做
newname=$(awk-F.“{print substr($2,2)”_e“$1”。$3}”
  • 使用bash的正则表达式匹配运算符
    =~
    ,以及捕获组(在
    (…)
    中的子字符串)来匹配每个文件名并提取感兴趣的子字符串
  • 匹配结果存储在特殊数组变量
    $BASH_REMATCH
    中,元素
    0
    包含整个匹配,
    1
    包含与第一个捕获组匹配的内容,
    2
    第二个捕获组,依此类推
  • 然后,
    mv
    命令的目标参数按照所需的顺序组合捕获组匹配项;注意,在本例中,为了简单起见,我将
    s{number}
    的零填充设置为无条件-a
    0
    只是在前面加上了前缀

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

您可以使用几乎纯的
bash
(使用):


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

根据模式重命名多个文件的常用方法是使用Perl命令。它使用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)
  • 。(.+)\u S2\.mp4
    捕获
    .
    \u S2.mp4
    之间的所有内容(放入
    $2
  • $2\u s02e$1.mp4
    根据需要将新文件名与捕获的数据组合在一起
当您对结果满意时,从命令中删除
-n
,它将真正重命名所有文件


rename
通常默认情况下在Linux上可用(包
util Linux
)。这里有一个关于查找/安装正确命令的详细说明。

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

ls -1 | \
    gawk 'match($0, /.../, a) { printf ... | "sh" } \
    END { close("sh") }'
为了便于阅读,我用省略号替换了正则表达式和
mv
命令

  • 第1行列出了当前目录中的所有文件名,每行一个,并将其传递到gawk命令
  • 第2行运行正则表达式匹配,将捕获的组分配给数组变量
    a
    。该操作使用
    printf
    将其转换为所需的命令,该命令本身通过管道传输到
    sh
    执行
  • 第3行关闭了在我们开始向它输送东西时隐式打开的外壳
因此,您只需填写正则表达式和命令语法(借用)。例如(实时代码警告)


要预览该命令(正如您应该做的那样),只需从第二行中删除
|“sh”

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

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

我假设这只适用于固定大小的字符串。如何在任意大小的字符串上用另一个扩展替换扩展?
$ 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
ls -1 | \
    gawk 'match($0, /.../, a) { printf ... | "sh" } \
    END { close("sh") }'
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") }'
ls | while read file; do newfile=`echo $file | awk -F . '{print $1 "." $2 "." $4}'`; echo $newfile;  mv $file $newfile; done;