【问题标题】:bash mass rename files in folders and subfolders with sequential numberbash批量重命名具有序列号的文件夹和子文件夹中的文件
【发布时间】:2017-07-25 06:31:25
【问题描述】:

我需要一个执行以下操作的 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 但没有成功! :(

谢谢

【问题讨论】:

    标签: bash rename sequential


    【解决方案1】:

    创建以下 bash 脚本并在您的音乐收藏的基本目录中执行它。它适用于包含空格、括号、单引号和双引号、其他奇怪字符的文件和目录名称,但 not 名称包含换行符或 really 奇怪字符。您可以自定义它为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-loving bash 从业者的注意事项:我知道使用mapfile 可能是在不显式创建$i 的情况下生成索引的一种聪明方法,但是(i) 不需要庞大的数组@ 987654332@ 将创建并且 (ii) 在解析传递给 mv 回调的命令行时,我仍然需要一个变量。)

    【讨论】:

      【解决方案2】:

      以下脚本为当前目录下的所有 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 > 4.0,据我所知,它没有预装在 mac 上(请咨询 bash --version)。但我听说有一些方法可以安装较新的 bash 版本。

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

      【讨论】:

      • 很好的解决方案,避免find 和随后的sort。但是,将所有路径名放在一个命令行中可能会达到 BSD ARG_MAX 262144 字节的限制。每个路径名估计平均 45 个字节(在我自己的音乐收藏中测量...)这将发生在大约 6000 个文件中...
      猜你喜欢
      • 2011-12-30
      • 1970-01-01
      • 2015-12-03
      • 2012-05-04
      • 1970-01-01
      • 2016-07-04
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      相关资源
      最近更新 更多