在Bash中重命名多个文件,但只更改文件名的一部分

97

我知道如何重命名文件等,但我在这方面遇到了麻烦。

我只需要在循环中重命名test-this

test-this.ext
test-this.volume001+02.ext
test-this.volume002+04.ext 
test-this.volume003+08.ext 
test-this.volume004+16.ext 
test-this.volume005+32.ext 
test-this.volume006+64.ext 
test-this.volume007+78.ext 

1
这里描述了几种可能性 - https://dev59.com/oG025IYBdhLWcg3wRDq8 - Tom Ron
这个答案也可能有用:https://unix.stackexchange.com/questions/316038/change-part-of-the-filename-on-multiple-files-in-a-directory - bfischi
6个回答

195

如果你将所有这些文件放在一个文件夹中,并且你使用的是Linux,你可以使用以下命令:

rename 's/test-this/REPLACESTRING/g' *

结果将会是:

REPLACESTRING.ext
REPLACESTRING.volume001+02.ext
REPLACESTRING.volume002+04.ext
...

rename 命令可以接受命令作为第一个参数。这里的命令由四个部分组成:

  1. s:用于替换某个字符串为另一个字符串的标志,
  2. test-this:你想要替换的字符串,
  3. REPLACESTRING:你想要将搜索字符串替换为的字符串,以及
  4. g:表示所有匹配的搜索字符串都将被替换的标志,即如果文件名是 test-this-abc-test-this.ext,则结果将是 REPLACESTRING-abc-REPLACESTRING.ext

有关这些标志的详细说明,请参阅 man sed


55
这个命令一直存在,我这辈子为什么没发现它?! - sanmiguel
7
重命名的实现方式取决于版本,另一个答案展示了相同命令但不同的实现语法。 - Will Barnwell
3
这在 Fedora 25 中包含的重命名不起作用。我必须执行 rename test-this REPLACESTRING *。有人知道在 Fedora 中安装哪个软件包可以获得答案中提到的重命名类型吗? - Aditya Kashi
2
@Dylan brew install rename - alandawkins
这就是为什么这里所有其他的评论已经解释了你正在使用的那个实用程序是另一个“rename”答案中的实用程序。 - tripleee
显示剩余6条评论

80

使用以下方式使用 rename 命令:

rename test-this foo test-this*

这将在文件名中用foo替换test-this

如果您没有rename命令,可以使用如下所示的for循环:

for i in test-this*
do
    mv "$i" "${i/test-this/foo}"
done

3
请注意,这是util-linux rename,不是另一个回答中提到的Perl rename。 (说明:此翻译尽力保持了原文的简洁和准确性,并遵循了所要求的指示,如有需要请在后续交流中提出) - wjandrea
2
这似乎是我Centos发行版中包含的重命名命令。显然,另一个重命名命令并不适用于Linux。 - Leslie Krause
1
两者都不是通用的。这就是为什么我们需要两个单独的答案。可能答案本身应该更明确和详细地说明这一点。 - tripleee

31

功能

我在OSX上,我的bash没有内置函数rename。我在.bash_profile中创建了一个函数,该函数接受第一个参数(应只匹配一次文件中的模式),并替换为第二个参数的文本。

rename() {
    for i in $1*
    do
        mv "$i" "${i/$1/$2}"
    done
}

输入文件

test-this.ext
test-this.volume001+02.ext
test-this.volume002+04.ext 
test-this.volume003+08.ext 
test-this.volume004+16.ext 
test-this.volume005+32.ext 
test-this.volume006+64.ext 
test-this.volume007+78.ext 

命令

rename test-this hello-there

输出

hello-there.ext
hello-there.volume001+02.ext
hello-there.volume002+04.ext 
hello-there.volume003+08.ext 
hello-there.volume004+16.ext 
hello-there.volume005+32.ext 
hello-there.volume006+64.ext 
hello-there.volume007+78.ext 

28
如果您已经安装了Homebrew,您可以使用brew install rename命令来安装rename - harryscholes
应该避免使用 for i in $1* 语法,因为它会在路径名中包含空格、星号、引号和其他奇怪字符时出错;使用 find . -iname "$1" -exec sh -c 'do work here' {} \; 更可靠,因为它可以正确处理任何路径名。 - ccpizza
很好用,而且在Cygwin中也能运行。 - undefined

14

不使用rename

find -name test-this\*.ext | sed 'p;s/test-this/replace-that/' | xargs -d '\n' -n 2 mv

它的工作方式如下:

  1. find 将查找与您的条件匹配的所有文件。如果您传递了一个 glob 表达式给 -name,请不要忘记转义 *

  2. 将以新行分隔的文件名列表管道传输到 sed 中,它将会:

    a. 打印 (p) 一行。

    b. 用替换后的内容打印 (s///) test-this 替换为 replace-that

    c. 移动到下一行。

  3. 将以新行分隔的旧文件名和新文件名列表的交替列表管道传输到 xargs 中,它将会:

    a. 将换行符视为分隔符 (-d '\n')。

    b. 每次调用带有多达 2 个 (-n 2) 参数的 mv 命令。

要进行干运行,请尝试以下操作:

find -name test-this\*.ext | sed 'p;s/test-this/replace-that/' | xargs -d '\n' -n 2 echo mv

*:请记住,如果您的文件名包含换行符,它将无法正常工作。


1
这个答案是UNIX的方式。这个答案适用于无数的应用程序,并且将支持像UNIX之神一样跳过云端。重命名答案是一次性的。 - Dell Kronewitter

1

将 index.htm 重命名为 index.html

rename [what you want to rename] [what you want it to be] [match on these files]
rename .htm .HTML *.htm

将index.htm重命名为index.html 它会为文件夹中所有匹配*.htm的文件执行此操作。

-2

感谢您的热情和回答。我也找到了一个解决方案,可以在Linux终端上重命名多个文件,并直接添加一个小计数器。这样我就有很好的机会拥有更好的SEO名称。

以下是命令:

count=1 ; zmv '(*).jpg' 'new-seo-name--$((count++)).jpg'

我也会进行编程直播视频,并将其发布到YouTube上。


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