我打算提出三个替代方案。每个都是一个简单的单行命令,但我会提供更复杂情况的变体,主要是为了处理与其他文件混在同一个目录中的文件。
mmv
我会使用mmv命令
来自于同名软件包:
mmv '*HBO_DPM*' '#1dpm#2'
请注意,参数以字符串形式传递,因此在shell中不会发生通配符扩展。该命令接收确切的两个参数,然后在内部查找相应的文件,对文件数量没有严格限制。还请注意,上述命令假设所有与第一个通配符匹配的文件都将被重命名。当然,您可以更具体地指定:
mmv 'sb_606_HBO_DPM_*' 'sb_606_dpm_#1'
如果您的文件位于同一目录中请求的数字范围之外,您可以考虑在此答案下方提供的循环遍历数字。但是您也可以使用适当模式的一系列 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
循环遍历数字
如果你想避免安装任何东西,或者需要通过数字范围选择来避免匹配超出此范围的内容,并且你愿意等待74,023次命令调用,你可以使用一个简单的bash循环:
for i in {0089000..0163022}; do mv sb_606_HBO_DPM_$i sb_606_dpm_$i; done
这在这里特别有效,因为序列中没有间隙。否则,您可能需要检查源文件是否实际存在。
for i in {0089000..0163022}; do
test -e sb_606_HBO_DPM_$i && mv sb_606_HBO_DPM_$i sb_606_dpm_$i
done
请注意,与for ((i=89000; i<=163022; ++i))
相比,花括号扩展可以处理前导零,因为几年前的某个Bash版本已经进行了更改。实际上,这是我提出的一个改变请求,所以我很高兴看到它的用例。
进一步阅读:在Bash信息页面中花括号扩展,特别是关于{x..y[..incr]}
的部分。
循环遍历文件
另一个选项是循环遍历适当的通配符,而不仅仅是在所讨论的整数范围内进行循环。类似于以下内容:
for i in *HBO_DPM*; do mv "$i" "${i/HBO_DPM/dpm}"; done
再次,每个文件只有一个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
在这里,${i##pattern}
会从$i
中删除最长的与pattern
匹配的前缀。这个最长的前缀被定义为任意字符,然后是一个下划线,接着是零个或多个零。后者被写成*(0)
,它是一个基于glob模式的扩展,取决于是否设置了extglob
选项。去除前导零非常重要,以将该数字视为十进制而不是八进制。循环参数中的+([0-9])
是另一个扩展的glob,用于匹配一个或多个数字,以防万一存在以相同开头但结尾不是数字的文件。
ARG_MAX
限制。由于这个问题明确要求命令行解决方案,所以其他问题中可能相等的GUI解决方案也不适用。 - dessertmv {1..2} {3..4}
不起作用,这是一个与ARG_MAX
完全不同的问题...其他回答的人可能也会有同样的感受!所以,从我的角度来看,我希望你能撤销你最后的编辑,并且如果你愿意的话,提出一个关于使用范围进行移动的全新问题。 - Zanna