在Bash中递归地更改文件扩展名

125

我希望递归遍历目录并更改特定扩展名的所有文件,例如将.t1更改为.t2。那么用于完成此操作的Bash命令是什么?

答:Bash命令如下:

find /path/to/directory -type f -name '*.t1' -exec rename 's/\.t1$/\.t2/' {} +

14
我认为这不是一个重复的问题,另一个问题不是递归的。 - shonky linux user
相关:https://askubuntu.com/questions/35922/how-do-i-change-extension-of-multiple-files-recursively-from-the-command-line - Ciro Santilli OurBigBook.com
@AmalAntony:如果你没有rename命令,可以编写一个shell脚本来重命名单个文件(在简单情况下很容易实现),然后使用find命令将此脚本应用于所有具有问题扩展名的文件。 - user1934428
6个回答

245

使用:

find . -name "*.t1" -exec bash -c 'mv "$1" "${1%.t1}".t2' - '{}' +

如果你有rename命令可用,则使用以下其中之一

find . -name '*.t1' -exec rename .t1 .t2 {} +
find . -name "*.t1" -exec rename 's/\.t1$/.t2/' '{}' +

20
在当前目录下查找所有以“.t1”结尾的文件,并将它们的扩展名改为“.t2”。命令为:find . -name '*.t1' -exec rename .t1 .t2 {} + - Aaron Blenkush
2
我的版本的 rename 不允许使用 sed 风格的替换表达式。Linux 真是太棒了。以前我还得在 Windows 上安装 TotalCommander 才能做这样的事情。 - Aaron Blenkush
7
如果有人像我一样好奇 "${1%.t1}".t2 这个部分是做什么的,这里有解释:它使用 bash 字符串操作来执行以下操作:1/ 从第一个位置参数 $1 中截取字符串字面量 .t1(百分号 % 操作符)。2/ 将 .t2 字符串字面量附加到结果上。 - Zack
5
建议使用命令 find . -type f -name '*.t1',以避免操作文件夹。 - Golak Sarangi
14
如果需要像这样一次重命名所有文件,则定界符参数应为;而不是+,例如:find . -name "*.t1" -exec bash -c 'mv "$1" "${1%.t1}".t2' - '{}' \;。否则,使用+只能一次重命名一个文件。参考链接 - S.aad
显示剩余7条评论

51

2
谢谢。在所选答案中重命名的东西在Ubuntu 20上不起作用。 - CaptainCodeman
这是唯一一个对我有效的方法。没有被接受的答案方法起作用。我使用的是Ubuntu,所以可能是Debian/CentOS之类的东西。谢谢。 - Neo
1
什么?Debian 14?你是来自未来的吗? - Dmytro Lysak

17

如果您使用的 bash 版本支持 globstar 选项(版本为4或更高):

shopt -s globstar
for f in **/*.t1; do
    mv "$f" "${f%.t1}.t2"
done 

11

我会在Bash中这样做:

for i in $(ls *.t1); 
do
    mv "$i" "${i%.t1}.t2" 
done

编辑: 我的错误:它不是递归的,这是我用于递归更改文件名的方法:

for i in $(find `pwd` -name "*.t1"); 
do 
    mv "$i" "${i%.t1}.t2"
done

10
不要解析ls(http://mywiki.wooledge.org/ParsingLs),同一页面上可以看到为什么你的 find 语法不好。另外,请确保引用您的变量 - Reinstate Monica Please

5
或者你可以直接安装 mmv 命令,并执行以下操作:
mmv '*.t1' '#1.t2'

这里的#1是第一个Glob部分,即*.t1中的*

如果使用纯Bash语法,一种简单的方法如下:

for f in *.t1; do
    mv "$f" "${f%.t1}.t2"
done

(i.e.: for 可以列出文件,不需要外部命令的帮助,例如 lsfind)
希望对你有所帮助。

8
我假定 OP 所使用的 "recursively" 是指在目录的子目录中重命名文件。 - chepner
1
它是第一个全局部分,即 *.t1 中的 * - zmo

1

我懒得复制粘贴这些解决方案中的一个,但我已经安装了fd-find,所以我使用了它:

fd --extension t1 --exec mv {} {.}.t2

fd的手册中得知,当执行一个命令(使用--exec)时:

          The following placeholders are substituted by a
          path derived from the current search result:

          {}     path
          {/}    basename
          {//}   parent directory
          {.}    path without file extension
          {/.}   basename without file extension

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接