批量重命名,*nix 版本

批量重命名,*nix 版本

我正在寻找一种方法来重命名大量名称相似的文件,很像这个(与 Windows 相关的问题)除了我使用 *nix (分别是 Ubuntu 和 FreeBSD) 之外。

总而言之,在使用 shell(Bash、CSH 等)时,如何批量重命名多个文件,例如以下文件:

Beethoven - Fur Elise.mp3
Beethoven - Moonlight Sonata.mp3
Beethoven - Ode to Joy.mp3
Beethoven - Rage Over the Lost Penny.mp3

会改名成这样吗?

Fur Elise.mp3
Moonlight Sonata.mp3
Ode to Joy.mp3
Rage Over the Lost Penny.mp3

我想要这样做的原因是这些文件集合将放在名为“贝多芬”(即文件名的前缀)的目录下,而文件名本身包含这些信息将是多余的。

答案1

Perl 的重命名实用程序会做你想做的事。

只需使用rename 's/Beethoven\ -\ //g' *.mp3

答案2

与 Linux/Unix 的许多事物一样,有多种方法可以做到!

有些可能会使用韓國(质量 mv)。

一些 Perl 包(较新的 Ubuntu 和 Debian)附带的重命名或预命名命令也可以执行此操作。

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

请注意,Fedora 10 上的重命名工具与此程序不同,并且工作方式也不同。它是另一个软件包 util-linux-ng 的一部分,可以在以下位置找到这里

我经常只是出于习惯而使用 shell for 循环(毕竟这样的工具并不总是存在)。

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

这将创建 Beethoven 目录,然后将文件移动到该目录/文件名,其中文件名中的“Beethoven - ”被替换为空。

作为测试,之前:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

后:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3

答案3

尝试这个解决方案,使用 grep 和 rename 的组合来实现。这是假设您有一大堆需要重命名的目录。如果只有几个,我会采用手动方法,为每个目录硬编码“Artist - ”模式。

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

解释寻找
寻找命令查找所有带有.mp3当前文件层次结构中的扩展,并调用传递给-执行对于每一个。请注意,在-执行{}指的是传递的参数寻找(文件路径+名称)。\;确保;传递到改名而不是表明寻找命令。

上面给出的命令有-n(无操作)开关;因此它只会告诉您运行它时会发生什么。我建议您在运行一次并对所提出的结果感到满意之后,才运行不带 -n 开关的此命令。

现在来看看正则表达式。

  • ^匹配字符串的开头。
  • $匹配字符串的结尾。
  • .匹配任意字符。
  • *表示零个或多个前一个构造。例如.*表示零个或多个字符。
  • \s代表任意空格字符。
  • \S代表任何非空格字符。
  • 其中的任何东西都会被捕获,并根据其位置()反映为$1、 。$2

正则表达式:

  • 在开始时寻找可选的目录结构,并在 $1 中捕获它:(.*/)
  • 跳过所有内容直到“ -”:.*-
  • 在 $2 中捕获字符串的其余部分(前导和尾随空格除外):(.*)
  • 将文件重写为 $1$2,即“/path/to/file/""filename.mp3”

这是我的测试运行:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

正则表达式是一件棘手的事情,我在编写它们时犯了很多错误,因此我欢迎任何关于这个缺陷的意见。我知道我发现有不少人对此进行了测试。

答案4

zmvzsh 重命名工具非常好。

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

更多注释请点击此处...

相关内容