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

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

8
这里是一个重命名命令的例子:
rename -n ’s/\.htm$/\.html/’ *.htm

-n表示这是一个测试运行,不会实际更改任何文件。它将显示一个列表,其中包含如果去掉-n将重命名的文件。在上述情况下,它将把当前目录中所有扩展名为.htm的文件转换为.html。
如果上面的测试运行输出看起来没问题,那么你可以运行最终版本:
rename -v ’s/\.htm$/\.html/’ *.htm

-v是可选的,但最好包含它,因为它是您将通过重命名命令进行更改的唯一记录,如下面示例输出所示:

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

中间棘手的部分是一个带有正则表达式的Perl替换,如下所示:

rename -v ’s/\.htm$/\.html/’ *.htm

7

一行代码,无需循环:

ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

例子:

$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json  ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt  ac8453e2-0d82-4d43-b80e-205edb754700.txt

+1 表示展示一种仅依赖于匹配现有扩展名的 bash 方法。这适用于任何输入扩展名,无论其长度是 3 个字符、4 个字符或更长。 - Ciprian Tomoiagă
改进:$ ls -1 | xargs -L 1 -I {} bash -c 'mv "$1" "${1%.*}.swift"' _ {} - Denis Kutlubaev
你不需要使用lsxargs;只需使用for f in ./*; do mv "$f" "${f%.*}.swift; done - undefined

5

mmv命令似乎可以在处理大量文件时(每秒数万个)非常高效地完成此任务。例如,要将所有.xml文件重命名为.html文件,请使用以下命令:

mmv ";*.xml" "#1#2.html"

;将匹配路径,*将匹配文件名,并且在替换名称中被称为#1#2

基于exec或管道的答案要么速度太慢,要么在大量文件上失败。


这是模糊且非标准的;它可能与https://github.com/rrthomas/mmv相同,但你链接的手册页面并没有透露关于它的来源或可用性的任何信息。 - undefined

4
这是一种同时修改多个扩展名的好方法:
for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

注意:要注意扩展大小相同(即 ???)。

4

在爬取别人的网站之后,我得到了一堆文件,这些文件没有 .html 扩展名,而且分布在许多子目录下。

为了一次性修改它们的名称(除了那些已经有 .html 扩展名的文件外,大部分文件都没有扩展名),以下方法对我很有用:

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

在OP的情况下,我可能会稍微修改一下,只重命名*.txt文件,如下所示:
find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

拆分(锤子时间!):

-iname *.txt
- 表示只考虑文件名已经以 .txt 结尾的文件

mv -iv "{}.{txt,html}" - 当 find 将 {} 作为文件名传递时,${filename%.*} 提取其没有扩展名的基本名称以形成 mv 的参数。 bash 使用 {txt,html} 重写它作为两个参数,因此最终命令运行为:mv -iv "filename.txt" "filename.html"

需要修复:处理文件名中的空格。


4

试试这个

rename .html .txt *.html 

使用方法:

rename [find] [replace_with] [criteria]

4

使用 shell 脚本为当前目录和子目录下的所有文件重命名文件扩展名(不需要其他软件包):

  1. Create a shell script rename.sh under current directory with the following code:

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
    
  2. Run it by ./rename.sh .old .new.

    Eg. ./rename.sh .html .txt


这与上面的查找解决方案存在相同的问题:您无法轻松地并行化它。当然,您可以在mv中添加&,但是那样您可能会产生100个或1000个衍生进程。使用xargs,您可以确保-P 20将允许最多20个分叉进程。 - Christian Bongiorno
for file in $(find ...) 对包含空格或shell元字符的文件名本质上是有问题的。请参阅https://mywiki.wooledge.org/BashFAQ/020 - undefined

3

有点晚了。您可以使用xargs来完成:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

如果您的所有文件都在某个文件夹中

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}

3
不要使用 ls 命令解析文件列表,这种做法很荒谬:它无用地在 ls 命令中使用通配符,而不是直接使用通配符。这样做会导致包含空格、引号和通配符字符的文件名出错。 - gniourf_gniourf
你可能需要知道,你所提供的文章中包含一个更新的注释,指出较新的LS版本在将文件输出到终端时已经正确地进行了 shell 转义处理。不过你提出的建议仍然是一个很好的经验法则。 - Katastic Voyage

3

最简单的方法是使用rename.ul,它在大多数Linux发行版中都存在。

rename.ul -o -v [旧文件扩展名] [新文件扩展名] [要应用于的文件搜索表达式]

rename.ul -o -v .oldext .newext *.oldext

选项:

-o:不覆盖已存在的.newext文件

-v:详细模式

-n:模拟运行


这让我感到惊讶,我今天才知道Ubuntu 20.04中有这个功能。谢谢! - james-see

3

与之前所建议的类似,这是我完成它的方式:

find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;

我首先使用了验证工具

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;

我最喜欢的答案 - Logemann

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