批量重命名,* nix版本


11

我一直在寻找一种方法来重命名大量类似命名的文件, 很像这个(与Windows相关的问题) 除了我正在使用* nix(Ubuntu和FreeBSD,另外)。总而言之,在使用shell(Bash,CSH等)的同时,我如何批量重命名一些文件,例如,以下文件:

贝多芬 - Fur Elise.mp3
贝多芬 - 月光奏鸣曲.mp3
贝多芬 - 对Joy.mp3的颂歌
贝多芬 - 失去了Penny.mp3的愤怒

将被重命名为这些?

Fur Elise.mp3
月光Sonata.mp3
对Joy.mp3的颂歌
愤怒超过失去的Penny.mp3

我想这样做的原因是这些文件集合将位于名为“Beethoven”的目录下(即文件名的前缀),并且文件名本身的这些信息将是多余的。

Answers:


12

重命名实用程序将执行您想要的操作。

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


你可以编辑提供该实用程序的链接,还是在提到的两个发行版(Ubuntu和FreeBSD)中都是标准的?
Chris W. Rea

1
它配备了Perl。 Debian使用它作为重命名命令,所以我怀疑Ubuntu也是如此。还有另一个“重命名”命令毫无价值,请查看手册页。
derobert

哇,重命名语法看起来非常相似vim替换:D
nXqd

/ usr / ports / sysutils / rename中的端口在FreeBSD中完美运行
Josh W.

10

像Linux / Unix这么多东西,有不止一种方法可以做到!

有些人可能会用 MMV (质量mv)。

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

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

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

我经常只是为了摆脱习惯而转向shell(毕竟这些工具并不总是存在)。

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

4

试试这个解决方案,使用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 当前文件层次结构中的扩展,并调用传递给的参数 -exec 为每个人。请注意 -exec {} 指的是传递的论点 (文件路径+名称)。该 \; 确保 ; 传递给 改名 而不是指示结束 命令。

上面给出的命令有 -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

Regexp是一个棘手的业务,我写了许多错误,所以我欢迎任何有关这个缺乏优点的意见。我知道我发现了不少测试。


1

我已经整理了一个命令行Java程序,它使重命名文件(和目录)变得轻而易举,特别是对于脚本编写。它是免费的开源软件,因此您可以根据自己的内容进行修改:

RenameWand
http://renamewand.sourceforge.net/

一些相关的用法示例:

移动表单的文件 "<a> - <b>" 到他们各自的目录 "<a>"

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

按上次修改时间对文件进行排序,并使用3位数字重命名:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

重新排列文件名的部分,并更改大小写:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"

1

zmv zsh重命名工具非常好。

# 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

这里有更多笔记......



0

这是一个简单的命令行示例。我在一堆png文件的名称中间有“white”这个词。我想把它拿出来,只留下一个下划线。这样就可以了:

for i in *.png; do mv "$i" "${i/white/}"; done

0

使用 vidir 然后使用编辑器功能应用重命名模式。

名称

vidir - 编辑目录

概要

vidir [--verbose] [目录|文件| - ] ...

描述

vidir允许在文本编辑器中编辑目录的内容。如果       没有指定目录,编辑当前目录。

编辑目录时,目录中的每个项目都将显示在其上       自己的编号线。这些数字是vidir如何跟踪哪些项目       改变了。删除行以从目录中删除文件,或进行编辑       用于重命名文件的文件名。您也可以将数字对切换为交换       文件名。

请注意,如果将“ - ”指定为要编辑的目录,则会读取列表       来自stdin的文件名,并显示那些用于编辑。或者,a       可以在命令行上指定文件列表。

例子

vidir      vidir * .jpeg          典型用途。

找到| vidir -          编辑子目录内容。要删除子目录,请删除所有           它们的内容和子目录本身在编辑器中。

find -type f | vidir -          编辑当前目录和子目录下的所有文件。

作者

乔伊赫斯2006-2010

Magnus Woldrich 2011的修改

版权

版权所有2006-2011 vidir“AUTHOR”如上所列。

根据GNU GPL许可。


0

在没有perl的* nix上 rename 可得到

在某些* nix上没有可用的重命名,所以有必要这样做 使用其他方法重命名。几年前我建议 zmv 虽然很棒,但也不一定可用。

使用builtins和sed,我们可以快速启动一个shell脚本 这给了我们与perl重命名脚本非常相似的语法, 虽然缺乏一些错误处理的好处,但它完成了工作。

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

用法

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

before:

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

after:

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

假设我们也想创建目标文件夹...

以来 mv 不会创建我们无法使用的文件夹 sedrename 原样 在这里,但这是一个相当小的变化,所以我觉得它很好 包括它。

我们需要一个效用函数, abspath (或绝对路径)所以我们可以 生成sed / rename模式的目标文件夹,包括 新的文件夹结构。

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

这将确保我们知道目标文件夹的名称。什么时候我们 重命名我们需要在目标文件名上使用它。

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

这是完整的文件夹识别脚本......

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

当然,当我们没有特定的目标文件夹时,它仍然有效 太。

如果我们想把所有歌曲放到一个文件夹中, ./Beethoven/ 我们做得到:

用法

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

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

after:

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

奖金回合......

使用此脚本将文件从文件夹移动到单个文件夹中:

假设我们想要收集匹配的所有文件,并放置它们 在当前文件夹中,我们可以这样做:

sedrename 's|.*/||' **/*.mp3

before:

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

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

关于sed正则表达式模式的注意事项

常规sed模式规则适用于此脚本,但这些模式不适用 PCRE(Perl兼容正则表达式)。你可以有sed 扩展正则表达式语法,使用任何一种 sed -r 要么 sed -E 取决于您的平台。

请参阅POSIX兼容 man re_format 有关的完整描述 sed基本和扩展的正则表达式模式。

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.