bash使用序号重命名文件夹和子文件夹中的文件

时间:2017-03-05 11:26:53

标签: bash rename sequential

我需要一个执行以下操作的bash脚本: 对于文件夹及其子文件夹中存在的某种类型的每个文件,它都会包含一个序号(4位),后跟一个分隔符( - )

例如,我有:

  /Queen/(1986) A Kind of Magic/01.One vision.mp3
  /Queen/(1986) A Kind of Magic/02.A kind of magic.mp3
  /Queen/(1986) A Kind of Magic/cover.jpg
  /Queen/(1991) Innuendo/01.Innuendo.mp3
  /Queen/(1991) Innuendo/02.Headlong.mp3
  /Queen/(1991) Innuendo/cover.jpg
  /Queen/(1991) Innuendo/booklet.pdf

我希望在脚本中有以下内容:

  /Queen/(1986) A Kind of Magic/0001-01.One vision.mp3
  /Queen/(1986) A Kind of Magic/0002-02.A kind of magic.mp3
  /Queen/(1986) A Kind of Magic/cover.jpg
  /Queen/(1991) Innuendo/0003-01.Innuendo.mp3
  /Queen/(1991) Innuendo/0004-02.Headlong.mp3
  /Queen/(1991) Innuendo/cover.jpg
  /Queen/(1991) Innuendo/booklet.pdf

请注意我在文件夹名称中的文件名和括号中有空格! 我怎样才能做到这一点?我试过mac automator但没有成功! :(

谢谢

2 个答案:

答案 0 :(得分:1)

创建以下bash脚本并在音乐集的基目录中执行它。它将使用包含空格,括号,单引号和双引号,其他奇怪字符的文件和目录名称,但,名称包含换行符或真正奇怪的字符。您可以自定义它,为start_dir提供不同的值,或更改格式规范%s/%04u-%s,目前包含%s(目录名称)%04u(编号索引,格式化)作为零填充的四位整数)和%s(文件名),由/-分隔。

#!/bin/bash
start_dir="."
find "$start_dir" -name '*.mp3' -type f \
  |sort \
  |while read name; do 
     ((i++))
     mv -i "$name" \
       "$(printf '%s/%04u-%s' "$(dirname "$name")" $((i)) "$(basename "$name")")"
   done

<强>说明:

Socowi的答案与我的非常相似。差异是(1)他需要bash 4.0,默认情况下不安装在Mac上。我不。 (2)他的脚本将使用包含换行符的文件名(非常罕见的场合)。我的不会。 (3) 如果所有mp3文件(包括子目录)的名称总长度超过262144字节,则他的脚本将失败;我会说如果你有超过6000个文件会发生这种情况。我将使用任意数量的文件。

(注意mapfile - 爱好bash从业者:我知道使用mapfile可能是一种生成索引而不明确创建$i的智能方法,但是(i)没有需要大型数组mapfile会创建和(ii)在解析传递给mv回调的命令行时,无论如何我都需要一个变量。)

答案 1 :(得分:0)

以下脚本为当前目录下的所有mp3文件添加四位数前缀,并且应该适用于所有可能的文件名。

#! /bin/bash
shopt -s globstar nullglob
n=0
for f in **/*.mp3; do
        (( ++n ))
        b="$(basename "$f")"
        mv -i "$f" "${f%"$b"}/$(printf '%04d' "$n")-$b"
done

globstar **需要bash&gt; 4.0据我所知,它没有预先安装在mac上(请与bash --version联系)。但我听说有很多方法可以安装更新的bash版本。

文件的编号顺序取决于您的区域设置。 Bash根据**/*按排序方式展开LC_COLLATE。至少LC_COLLATE=en_US.UTF-8个文件按字母顺序编号,我们不必担心名称冲突 - 保证不会发生覆盖。