如何为一堆文件重命名扩展名?

557
在一个目录中,我有一堆*.html文件。我想把它们全部重命名为*.txt
我该怎么做呢? 我使用Bash shell。
28个回答

771
如果使用Bash,就不需要像sed、basename、rename、expr等外部命令。
for file in *.html
do
  mv "$file" "${file%.html}.txt"
done

17
如果您不知道文件扩展名,可以使用"${file%.*}.txt",但对于没有扩展名的文件来说可能存在危险。 - Jess
2
提醒那些像我一样遇到问题的人:请注意花括号内部没有 $ 符号! - doug65536
9
我需要一种永久收藏/书签此答案的方法,我总是记不住确切的语法,最终只能通过谷歌搜索找到它。 - boliva
10
百分号括号结构可以从末尾删除字符,而井号括号结构可以从开头删除字符。请查看:http://tldp.org/LDP/abs/html/parameter-substitution.html#PSUB2 - user755921
6
另一个 Stack exchange 的回答(我找不到了!)建议使用以下命令,同时使用 -- "运算符":mv -- "$file" "${file%.html}.txt"。该运算符可以防止以 '-' 开头的文件名被 mv 解析为参数。 - rcreswick
显示剩余3条评论

417

以下代码可行且不需要系统拥有 rename 程序(尽管大多数系统通常都有这个程序):

对于更好的解决方案(只使用bash功能,而不是外部调用),请参见其他答案之一

for file in *.html; do
    mv "$file" "$(basename "$file" .html).txt"
done

编辑:如评论所指出,如果文件名中含有空格,则没有进行适当引用将无法正常工作(现已添加)。当仅处理您自己知道文件名不包含空格的文件时,这将起作用,但每当您编写可能在以后重复使用的内容时,请不要忽略适当的引用。


55
一个没有basename且包含引号的替代方案:mv "${file}" "${file/%.html/.txt}"(请参见bash手册中的Parameter Expansion以获取详细信息)。 - Rodrigo Queiro
9
只有当文件都在当前目录时才有效,因为basename会剥离路径名部分。这只是一个“需要注意”的提示! - Jonathan Leffler
7
这个解决方案不好,不仅速度慢,而且无法处理文件名中带空格的情况。在bash脚本中,你应该始终进行适当引用。mv "$file" "$(basename "$file" .html)".txt会更好一些。但是,mv "$files" "${files%.html}.txt"会更好。 - Balázs Pozsár
13
在Windows中,您只需执行ren *.a *.b - Muhammad Umer
2
至少要使用POSIX规定的$()语法,而不是传统的反引号语法。这样可以提高可读性,并且当您需要在命令替换中使用需要反斜杠转义才能成为字面值的字符时,使语法更加清晰明了。 - Charles Duffy
显示剩余6条评论

206
rename 's/\.html$/\.txt/' *.html

完全符合你的要求。


我认为您不能像您建议的那样在Bash中使用字面正则表达式 - 您正在使用哪个Shell? - DaveR
这是Ubuntu版本的rename命令的man手册页面:http://unixhelp.ed.ac.uk/CGI/man-cgi?rename - Amber
rename是一些系统上的命令。我有一个Perl脚本(最初来自第一本Camel书),可以完成这项工作。还有一个GNU程序,名称相同,可以完成大致相同的工作。我的Mac没有提供' rename'命令 - 或者它没有在我的PATH上(这是相对全面的)。 - Jonathan Leffler
Homebrew 中有一个重命名公式。 - revprez
我喜欢你的回答。但实际上,我只会使用 rename 's/jpg/png/' *.jpg,这样更容易记忆和输入。如果有文件名包含 jpg,则可能会导致错误,因此在输入之前我会先检查一下。 - ramwin

151

这对我在OSX上从.txt到.txt_bak的转换有效。

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;

5
在Linux中也能正常工作。 - Diziet
这不是重点,但是要从.txt变成.txt_bak,你只需要连接_bak ;) - corwin.amber
4
这对于递归重命名很不错。 - leachryanb
1
太好了!(在Ubuntu 16.04下)我的实际用例是将所有.scss重命名为.sass(在原地转换后...):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \; - Frank N
3
此方法适用于6000多个文件,重命名时报错“参数列表过长”。 - Tony Cronin
我在Windows中使用GIT hooks(这意味着shell(Linux)) - 它工作良好。我想删除.tmp扩展名,所以我稍微修改了一下: find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.tmp}"' {} ; (如果有人想将扩展名重命名为空(删除文件的.tmp扩展名) 感谢@Steven - Teo

102

你想使用rename命令:

rename -S <old_extension> <new_extension> <files>

rename -S .html .txt *.html

这正好做到了你想要的——它将会把所有匹配*.html的文件的扩展名从.html更改为.txt

注意:Greg Hewgill 正确指出这不是一个 bash 内置命令;而是一个单独的 Linux 命令。如果你只需要在 Linux 上使用,那么这应该能很好地工作;如果你需要更跨平台的东西,请看看其他答案中的一个。


10
虽然这是一个不错的解决方案,但 rename 程序与 bash 没有关联,并且也不支持所有平台。我只在 Linux 上看到过它。 - Greg Hewgill
15
"$rename .html .txt *.html" 的结果是语法错误,位于(eval 1)第1行附近的“.”。 - Amber
8
正确的语法是rename -S .html .text *.html,其中-S代表--subst-all - Marek Sebera
4
可使用HomeBrew在Mac OS上更改名称。 - CodeBrauer
5
util-linux 2.28.2 的 rename 命令没有 -S 选项,但即使没有该选项,它仍然可以正常工作。 - Torsten
显示剩余6条评论

36

在Mac上...

  1. 如果尚未安装rename,请执行以下命令进行安装:brew install rename
  2. rename -S .html .txt *.html

16

对于Ubuntu用户:

rename 's/\.html$/\.txt/' *.html

这不是递归的,但在Ubuntu 14.04上对我有效。 - Max Wallace

16

这是我在OSX和Linux上找到的最简洁的解决方案,而且它也可以很好地与git一起使用!

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

同时,与git一起使用:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;


不是很流畅,因为它为每个文件启动一个新的bash。实际上相当慢。请使用管道和xargs。 - Holger Jakobs
我想这是真的。我无法想象有很多情况下你需要命名那么多文件,以至于性能会受到影响。这种方法可以在几秒钟内重命名数百个文件。所以,我猜也许它的性能不是很好,但如果你不需要考虑性能,这是一个漂亮的解决方案... - bdombro
与xargs解决方案相比,这里还有另一个限制:您无法轻松并行化它。使用xargs,您只需添加-P 10即可将命令分叉为最多10个并发进程。非常适合处理大型目录。使用ls -1只是如何向xargs提供输入的示例 - 您也可以将其与find一起使用。 - Christian Bongiorno

10

这个问题明确提到了Bash,但如果你恰好有ZSH可用,那么它就非常简单:

zmv '(*).*' '$1.txt'

如果你看到zsh: command not found: zmv,那么只需运行:

autoload -U zmv

然后再试一遍。

感谢这篇原始文章提供了关于zmv的技巧。


使用原始问题中的特定文件扩展名,将zmv '(*).html' '$1.txt'翻译为中文。 - Alf Eaton

8
在 Linux 或 Windows 的 Git Bash 或 Windows 的 WSL 中,可以尝试以下命令来更改当前目录或子目录甚至它们的子目录中每个文件的扩展名,只需一行代码。
find . -depth -name "*.html" -exec sh -c 'mv "$1" "${1%.html}.txt"' _ {} \;

1
在我的 Windows 11 Git Bash(MINGW64)中运行良好。 - Ralph

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