我必须再次创建我的问题,因为所有找到的解决方案都不适合我的情况。处理许多填充时,我想使用一些单行实用程序,它允许在文件名中进行多次替换。这是输入文件名称的格式
1300_grid12_04_lig_cne_767_lig.dlg
这是预期的输出:
130004_lig_cne_767.dlg
因此,对于每个文件,我必须替换两种模式“网格12" 到 "_" 和 "_lig." 到 "." 手动对于填充的整体,我可以使用两个后续循环来实现它,这是处理大量填充的非常慢的方法。
# 1st loop over the files and substitute patter _grid12_ to _.
for file in ./*.dlg; do mv -v "$file" "${file/_grid12_/_}"; done
# 2nd loop these filles to substitute _lig. to .
for file in ./*.dlg; do mv -v "$file" "${file/_lig./.}"; done
我已经尝试过重命名命令,但它无法正确识别模式:
rename 's/_grid12_/_/g' *.dlg
是否可以避免循环填充以快速完成此操作?
答案1
这应该会使循环速度加快两倍,因为它将每个文件直接重命名为最终名称。
for file in ./*.dlg; do
new=${file/_grid12_/_}
mv -v "$file" "${new/_lig./.}"
done
您可能可以通过并行运行重命名来获得一些加速(但 IO 可能很容易成为瓶颈):
cpu_tally=$(grep -c ^processor /proc/cpuinfo)
for file in ./*.dlg; do
new=${file/_grid12_/_}
printf '%s\0' "$file" "${new/_lig./.}"
done | xargs -r0 -n2 -P$cpu_tally -exec mv -v
答案2
缓慢的是mv
为每个文件执行独立实用程序。您可以切换到可以内置zsh
该实用程序的位置:mv
zmodload zsh/files # makes mv and a few other file manipulation utilities builtin
autoload -Uz zmv # batch renaming tool
zmv -v '*.dlg' '${${f/_grid12_/_}/_lig./.}'
zmv
与简单循环相比具有额外的功能。例如,如果发现冲突,它将在开始重命名之前中止。
简单的循环可以是:
for f (*.dlg(#qoN)) mv -vi -- ${${f/_grid12_/_}/_lig./.}
这里还添加了一个(#qoN)
glob 限定符来禁用排序。
答案3
touch 1300_grid12_04_lig_cne_767_lig.dlg
# if you have few
parallel mv {} '{= s/_grid12_04//; s/_lig.dlg/.dlg/ =}' ::: *.dlg
# if you have thousands
printf "%s\0" *.dlg |
parallel -0 mv {} '{= s/_grid12_04//; s/_lig.dlg/.dlg/ =}'
ls 1300*dlg