使用 bash 重命名大量图像文件

ric*_*ich 16 command-line bash batch-rename

我需要重命名大约。70,000 个文件。例如:从sb_606_HBO_DPM_0089000sb_606_dpm_0089000等。

数字范围从00890000163022。这只是名称的第一部分需要更改。所有文件都在一个目录中,并按顺序编号(图像序列)。数字必须保持不变。

当我在 bash 中尝试此操作时,它对我说“参数列表太长”感到恼火。

编辑:

我首先尝试使用以下命令重命名单个文件mv

mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx
Run Code Online (Sandbox Code Playgroud)

然后我尝试重命名一个范围(我上周在这里学到了如何移动大量文件,所以我认为相同的语法可能适用于重命名文件......)。我我尝试了以下(或类似的):

mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx
Run Code Online (Sandbox Code Playgroud)

Zan*_*nna 26

一种方法是使用findwith-exec+选项。这将构造一个参数列表,但将列表分解为所需数量的调用,以在不超过最大参数列表的情况下对所有文件进行操作。当所有参数都被同等对待时是合适的。这是 的情况rename,尽管不是mv

您可能需要安装 Perl 重命名:

sudo apt install rename
Run Code Online (Sandbox Code Playgroud)

然后你可以使用,例如:

find . -maxdepth 1 -exec rename -n 's/_HBO_DPM_/_dpm_/' {} +
Run Code Online (Sandbox Code Playgroud)

-n测试后删除,以实际重命名文件。


MvG*_*MvG 11

我将建议三种选择。每个都是一个简单的单行命令,但我会为更复杂的情况提供变体,主要是在要处理的文件与同一目录中的其他文件混合的情况下。

毫米波

我会用MMV命令包同名

mmv '*HBO_DPM*' '#1dpm#2'
Run Code Online (Sandbox Code Playgroud)

请注意,参数是作为字符串传递的,因此在 shell 中不会发生 glob 扩展。该命令只接收两个参数,然后在内部查找相应的文件,对文件数量没有严格限制。另请注意,上面的命令假定所有与第一个 glob 匹配的文件都应重命名。当然,您可以自由地更具体:

mmv 'sb_606_HBO_DPM_*' 'sb_606_dpm_#1'
Run Code Online (Sandbox Code Playgroud)

如果您在同一目录中有超出请求的数字范围的文件,那么您可能会更好地使用本答案中进一步给出的数字循环。但是,您也可以使用具有合适模式的一系列 mmv 调用:

mmv 'sb_606_HBO_DPM_0089*'       'sb_606_dpm_0089#1'    # 0089000-0089999
mmv 'sb_606_HBO_DPM_009*'        'sb_606_dpm_009#1'     # 0090000-0099999
mmv 'sb_606_HBO_DPM_01[0-5]*'    'sb_606_dpm_01#1#2'    # 0100000-0159999
mmv 'sb_606_HBO_DPM_016[0-2]*'   'sb_606_dpm_016#1#2'   # 0160000-0162999
mmv 'sb_606_HBO_DPM_01630[01]?'  'sb_606_dpm_01630#1#2' # 0163000-0163019
mmv 'sb_606_HBO_DPM_016302[0-2]' 'sb_606_dpm_016302#1'  # 0163020-0163022
Run Code Online (Sandbox Code Playgroud)

循环数字

如果您想避免安装任何东西,或者需要按数字范围进行选择以避免此范围之外的匹配,并且您准备等待 74,023 个命令调用,则可以使用普通的 bash 循环:

for i in {0089000..0163022}; do mv sb_606_HBO_DPM_$i sb_606_dpm_$i; done
Run Code Online (Sandbox Code Playgroud)

这在这里特别有效,因为序列中没有间隙。否则,您可能需要检查源文件是否实际存在。

for i in {0089000..0163022}; do
  test -e sb_606_HBO_DPM_$i && mv sb_606_HBO_DPM_$i sb_606_dpm_$i
done
Run Code Online (Sandbox Code Playgroud)

请注意,与for ((i=89000; i<=163022; ++i))大括号扩展相比,自从几年前发布了一些 Bash 以来,它确实处理了前导零。实际上是我要求的更改,所以我很高兴看到它的用例。

进一步阅读: Bash 信息页面中的Brace Expansion,特别是关于{x..y[..incr]}.

循环文件

另一种选择是循环一个合适的 glob,而不是仅仅循环有问题的整数范围。像这样的东西:

for i in *HBO_DPM*; do mv "$i" "${i/HBO_DPM/dpm}"; done
Run Code Online (Sandbox Code Playgroud)

同样,这是mv每个文件一次调用。再次循环遍历一长串元素,但整个列表不会作为参数传递给子进程,而是由 bash 内部处理,因此限制不会给您带来问题。

进一步阅读: Bash 信息页面中的Shell Parameter Expansion${parameter/pattern/string}以及其他文档。

如果您想将数字范围限制为您提供的数字范围,您可以为此添加一个检查:

for i in sb_606_HBO_DPM_+([0-9]); do
  if [[ "${i##*_*(0)}" -ge 89000 ]] && [[ "${i##*_*(0)}" -le 163022 ]]; then
    mv "$i" "${i/HBO_DPM/dpm}"
  fi
done
Run Code Online (Sandbox Code Playgroud)

这里${i##pattern}删除最长前缀匹配pattern$i。最长的前缀被定义为任何东西,然后是下划线,然后是零个或多个零。后者被写成*(0)这是一个扩展的glob 模式,取决于正在设置的extglob选项。删除前导零对于将数字视为基数 10 而不是基数 8 很重要。+([0-9])in the loop 参数是另一个扩展的 glob,匹配一个或多个数字,以防万一您的文件开始相同但不以 a 结尾数字。


ste*_*ver 10

解决此ARG_MAX限制的一种方法是使用 bash shell 的 builtin printf

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'
Run Code Online (Sandbox Code Playgroud)

前任。

rename -n 's/HBO_DPM/dpm/' sb_*
bash: /usr/bin/rename: Argument list too long
Run Code Online (Sandbox Code Playgroud)

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'
rename(sb_606_HBO_DPM_0089000, sb_606_dpm_0089000)
.
.
.
rename(sb_606_HBO_DPM_0163022, sb_606_dpm_0163022)
Run Code Online (Sandbox Code Playgroud)


αғs*_*нιη 7

find . -type f -exec bash -c 'echo $1 ${1/HBO_DPM/dpm}' _ {} \;
./sb_606_HBO_DPM_0089000 ./sb_606_dpm_0089000
Run Code Online (Sandbox Code Playgroud)

find在当前目录下.的所有文件-type f和做重命名文件中发现$1有更换HBO_DPMdmp 一个接一个-exec ... \;

更换echomv进行重命名。


muc*_*lux 6

您可以逐个文件(可能需要一些时间)使用

sudo apt install util-linux  # if you don't have it already
for i in *; do rename.ul HBO_DPM dpm "$i"; done
Run Code Online (Sandbox Code Playgroud)

rename其他答案中使用的 Perl 一样,rename.ul也有一个选项-n--no-act用于测试。


小智 6

你可以写一个小的python脚本,比如:

import os
for file in os.listdir("."):
    os.rename(file, file.replace("HBO_DPM", "dpm"))
Run Code Online (Sandbox Code Playgroud)

将其另存为rename.py文件所在文件夹中的文本文件,然后在该文件夹中使用终端:

python rename.py
Run Code Online (Sandbox Code Playgroud)