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


479

在目录中,我有一堆*.html文件。我想将它们全部重命名为*.txt

我怎样才能做到这一点?我使用bash外壳。

Answers:


382

要获得更好的解决方案(仅具有bash功能,而不是外部调用),请参阅其他答案之一


以下将执行并且不需要系统具有该rename程序(尽管您通常会在系统上拥有该程序):

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

编辑:正如评论中指出的那样,这对于没有适当引号的文件名(在上面已添加)不起作用。当纯粹在自己的文件上工作(您知道文件名中没有空格)时,这将起作用,但是每当您编写以后可以重用的内容时,请勿跳过正确的引用。


47
一个没有基名且带引号的替代方法:mv“ $ {file}”“ $ {file
/%。html

7
当然,只有文件都在当前目录中,这才是好方法,因为basename会删除路径名部分。只是“当心”!
乔纳森·勒夫勒

6
这种解决方案是不好的,不仅因为它速度慢,而且因为它不适用于其中带有空格的文件名。您应该始终在bash脚本中进行正确的引用。mv“ $ file”“ $(basename” $ file“ .html)”。txt会好得多。但是,MV“ $ files”“ $ {files%.html} .txt”更好。
巴拉兹Pozsár

8
在Windows中就可以做ren *.a *.b
穆罕默德·乌默尔

2
至少应使用POSIX指定$()的语法,而不要使用旧的反引号语法。改进了可读性,并且当您有一些字符需要用反斜杠转义以在用命令替换的字符内成为原义时,语法就变得不那么模棱两可了。
Charles Duffy

667

如果使用bash,则不需要sed,basename,rename,expr等外部命令。

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done

12
而且,如果您不知道可以使用的文件扩展名"${file%.*}.txt",但这对于完全没有扩展名的文件可能会很危险。
杰西

1
请注意任何无法像我一样工作的人:请注意,$花括号内部没有!
doug65536

5
我需要一种方法来永久地收藏/收藏这个答案,我不记得确切的语法了,因此我最终搜索了它
boliva 2014年

7
@danip括号内的百分号构造将字符从末尾剥离。还有一个括号内的散列结构,可将字符从开头删除。检查它:tldp.org/LDP/abs/html/parameter-substitution.html#PSUB2

4
另一个Stack交换答案(我找不到!)建议这样做,但也可以使用--“ operator”:mv-“ $ file”“ $ {file%.html} .txt”该运算符可防止以mv将其解析为参数的“-”。
rcreswick

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

正是您想要的。


我认为您不能像您建议的那样在bash中使用文字正则表达式-您使用的是哪个shell?
DaveR

1
我使用的是Mac终端
bmw0128,2009年

这是Ubuntu上重命名版本的手册页:unixhelp.ed.ac.uk/CGI/man-cgi?rename
Amber

在某些系统上,重命名是命令。我有一个Perl脚本(最初来自第一本Camel书)来完成这项工作。还有一个同名的GNU程序,其功能大致相同。我的Mac没有系统提供的“重命名”命令-或我的PATH上没有此命令(此命令比较全面)。
乔纳森·勒夫勒

Homebrew中有一个重命名公式。
revprez

112

这在OSX上对我有效,从.txt到.txt_bak

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

4
在Linux中也可以正常工作。
Diziet

这不是重点,但是要连接.txt.txt_bak您,就必须串联_bak;)
corwin.amber16'7

3
这非常适合递归重命名
leachryanb

大!(在Ubuntu 16.04下)我的实际用例,将所有名称重命名.scss.sass(就地转换后):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Frank Nocke

2
这与+6000文件一起使用,重命名报告“参数列表太长”
Tony Cronin

94

您要使用rename

rename -S .html .txt *.html

这正是您想要的,它会将所有匹配的文件的扩展名从.html更改.txt*.html

注意:Greg Hewgill正确指出这不是内置的bash;并且是单独的Linux命令。如果您只需要Linux上的某些功能,则应该可以正常工作。如果您需要更多跨平台的内容,请查看其他答案之一。


7
尽管这是一个很好的解决方案,但是该rename程序与之无关,bash并且并非在所有平台上都可用。我只在Linux上看到过它。
Greg Hewgill

15
“ $ rename .html .txt * .html”导致...的语法错误,位于(eval 1)第1行,靠近“”。
琥珀色

8
正确的语法是rename -S .html .text *.html其中-S代表--subst-all
马立克Sebera

8
brew install重命名
Nick

4
@GregHewgill重命名可用于带有HomeBrew的Mac OS
CodeBrauer 2014年



9

这是我发现的最光滑的解决方案,可在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' - '{}' \;


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

6

这个问题明确提到了Bash,但是如果您碰巧有ZSH可用,则非常简单:

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

如果得到,zsh: command not found: zmv则只需运行:

autoload -U zmv

然后再试一次。

感谢这篇原始文章作为有关zmv的技巧。


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

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

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

;将匹配的路径时,*将匹配的文件名,并且这些称作#1#2在替换名称。

对于exec大量文件,基于或管道的答案太慢或失败。


3

尝试这个

rename .html .txt *.html 

用法:

rename [find] [replace_with] [criteria]

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。这个命令很荒谬:它无用地使用了带有的glob ls,而不是直接使用glob。这将破坏包含空格,引号和(由于缺少引号)glob字符的文件名。
gniourf_gniourf

仅供参考,您的链接文章包含更新的注释,其中指出较新的LS“如果打印到终端上,则“正确地逃脱”文件”。您的观点仍然是一个很好的经验法则。
Katastic Voyage,

3

这是一次修改多个扩展名的好方法:

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

注意:注意扩展名的大小要相同(???)


2

尼斯和简单!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;

2

如果您更喜欢PERL,可以使用一个简短的PERL脚本(最初由PERL的创建者Larry Wall编写),该脚本可以完全满足您的要求: tips.webdesign10.com/files/rename.pl.txt

对于您的示例,以下方法可以解决问题:

rename.pl 's/html/txt/' *.html

2
这个问题已经很久以前就已经被回答并接受了,似乎您的回答所带来的没有比已经说的更多。
ChristopheLec

1
+1,因为它是Larry Wall脚本(由Robin Barker修改)。最后一个可用的网址是:tips.webdesign10.com/files/rename.pl.txt
loretoparisi

1

与之前建议的类似,这是我的做法:

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

我首先用

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

1

一行,没有循环:

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个字符长或更多
CiprianTomoiagă

0

不幸的是,可移植性并不是一件容易的事。您可能需要一点expr魔术。

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

一旦您满意,请删除回声。

编辑: basename尽管expr通常更灵活,但在这种情况下可能更具可读性。


虽然这可能不是问题的最佳答案,但这是对我来说!我需要一种仅在字符串中重命名整个路径的方法,而不仅仅是文件名。感谢您的发布!
donut

0

这是我用来重命名.edge文件的地方.blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

像魅力一样工作。


0

您还可以在Bash中创建一个函数,将其添加到.bashrc或其他内容中,然后在任何需要的地方使用它。

change-ext() {
    for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}

用法:

change-ext css scss

函数中的代码源:https : //stackoverflow.com/a/1224786/6732111


0

重命名当前目录和子目录下所有文件的文件扩展名,而无需任何其他软件包(仅使用shell脚本):

  1. rename.sh使用以下代码在当前目录下创建一个shell脚本:

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

    例如。 ./rename.sh .html .txt

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.