Bash 脚本重命名文件(不包括数组中的名称)

Bash 脚本重命名文件(不包括数组中的名称)

我目前有一个脚本,可以通过删除空格和某些名称来重命名文件。到目前为止,大约有 200 个名称,因此我认为要排除的名称数组将是更好的选择。

prename -v 's/ /_/g' *

prename -v 's/_-_/_/g' *

prename -v 's/_\(Summer-HD\)//ig' *

prename -v 's/_\(Hammer\)//ig' *

prename -v 's/_\(Hardware-Hybrid\)//g' *

prename -v 's/_\(digital\)//ig' *

prename -v 's/_\(Resolution-SD\)//ig' *

这是我到目前为止所尝试过的,一个 for 循环来迭代我想要排除的名称,但这并没有奏效。

exclude=('(Summer-HD)' '(Hammer)' '(digital)' '(Resolution-SD)' '(Vacation)' '(Hammer-Hybrid)')

for x in "${exclude[@]}";
    do prename -v 's/$x/_/g' * {} \;
done

这个 for 循环根本不起作用,只留下一个闪烁的光标。我不确定是否可以将变量传递给 prename。我根据一些有关用双引号括起来的建议对 for 循环进行了一些修改。

for x in "${exclude[@]}";
    do prename -v 's/$x/_/g' *"$x"* {} \;
done

这也行不通,现在我不知道这里发生了什么。我仍然想要名称数组,因为我目前有 200 多个名称想要删除。至于名字,我不同意这个想法,我听说 sed 或 awk 可以提供帮助。我都不愿意这样做。感谢您提供的任何想法或帮助。

答案1

您可以在脚本内定义数组(或包含由列表组成的正则表达式的标量变量)prename- 请记住,您可以在 prename 脚本内使用任何有效的 perl 代码(因为 prename 脚本专门的 Perl 脚本)。例如

$ touch foo_\(Summer-HD\)_\(digital\).mkv
$ prename -n 'BEGIN {
                our $exclude=join("|", qw(Summer-HD Hammer digital Resolution-SD Vacation Hammer-Hybrid));
              };

              our $exclude;
              s/_\((?:$exclude)\)//ig;' *
rename(foo_(Summer-HD)_(digital).mkv, foo.mkv)

这里有几点值得注意:

  1. 变量范围在重命名脚本中非常重要,并且编译use strict指示有效。看perldoc strict(还有很多内容,但是,长话短说:strict不能使用之前未在当前范围内声明的变量)。
  2. $exclude变量在块中定义BEGIN {},以便在执行脚本时仅执行一次,而不是每个文件名执行一次。它包含由字符连接的数组|- 即正则表达式交替。
  3. 它被定义为一个our变量,以便在 BEGIN 块之外共享,即它在File::Rename包的整个范围内可用。这可能超出了您想知道的范围,因此只需将其视为重命名脚本的全局变量即可。主代码块也需要声明它(仅使用our $exclude;)。看perldoc -f our
  4. qw()是 Perl 的引用运算符之一,它将空格分隔的裸词列表转换为数组。看perldoc -f qw。顺便说一句,在 perl 中,“数组”和“列表”几乎是同义词 - 请参阅perldoc -q difference.*list.*array

另外值得注意的是,rename您应该使用较长的脚本(或多个选项)运行一次,而不是多次运行-e '...script...'。例如

$ prename -n 'BEGIN {
                our $exclude=join("|", qw(Summer-HD Hammer digital Resolution-SD Vacation Hammer-Hybrid));
              };

              our $exclude;

              s/ /_/g;
              s/_-_/_/g;
              s/_\((?:$exclude)\)//ig;' *

答案2

使用以下方法更容易zsh

exclude=(
  '(Summer-HD)'
  '(Hammer)'
  '(digital)'
  '(Resolution-SD)'
  '(Vacation)'
  '(Hammer-Hybrid)'
)

pattern="_(${(j[|])${(b@)exclude}})"

autoload -Uz zmv
zmv '*' '${f//$~pattern}'

其中${(b)exclude}转义 元素中的全局运算符$exclude${(j[|])...}将结果与 联接|,因此我们最终得到$patternbeing _(exclude1|exclude2...)(特别是:),并且使用批处理重命名器内的 ksh93 中的运算_(\(Summer-HD\)|\(Hammer\)|\(digital\)|\(Resolution-SD\)|\(Vacation\)|\(Hammer-Hybrid\))符将其匹配项替换为空。${f//pattern[/replacement]}zmv

相关内容