这感觉很简单,但我完全被难住了。不用说我对此完全陌生。我有一个目录,其中的文件编号从000
到020
。我想通过添加 1 来重命名这些文件,以便000
成为001
等。理想情况下使用awk
命令,但任何建议将不胜感激,谢谢。
没有前缀,000
是整个名称。没有标记为 的文件021
。
答案1
使用zsh
代替bash
,你可以这样做:
autoload -Uz
zmv -f -n '*(#qnOn)' '${f//(#m)<->/${(l[3][0])$((MATCH+1))}}'
将当前目录中的文件名中的每个数字增加并用 0 填充它们的长度,使其长度为 3。例如foo-1-2-003.ext
重命名为foo-002-003-004.ext
或。012
013
(如果整个文件是一个数字,那就zmv -f -n '<->(#qnOn)' '${(l[3][0])$((MATCH+1))}'
足够了,或者<0-20>
只<->
重命名0到20之间的文件,或者<0-20>~^[0-9](#c3)
用3位数字表示的0到20之间的文件)。
替换是使用ksh
-style计算的${var//pattern/replacement}
,模式为(#m)<->
,(#m)
以触发捕获匹配的内容$MATCH
并<->
匹配任何十进制数字序列( 的无界形式<3-12>
)。 left l[width][pad]
-padding 参数扩展标志用于填充。
我们使用和限定符按其名称的反向n
数字顺序对文件列表进行排序,以确保重命名为之前重命名为。O
n
n
On
q
file002
file003
file001
file002
禁用健全性检查,这里会抱怨在源中也找到了一些目的地,但这意味着如果同时存在 a和文件,-f
它不会防止数据丢失。file1
file01
如果您没有 zsh,但有 bash 和名为 000 到 020 的文件存在,并且是您想要重命名的文件(如您稍后澄清的那样),您可以执行以下操作:
for file in {020..000}; do
printf -v new %03d "$(( 10#$file + 1 ))"
mv "$file" "$new"
done
{020..000}
(bash实际上是从 zsh 复制的,而 zsh-v
从 bash 复制的,该代码在两个 shell 中都可以工作;10#
和 引号在 中不是必需的zsh
)。
在这里,由于文件名非常驯服,您还可以执行以下操作:
ls -rq | LC_ALL=C awk '
/^[0-9]{3}$/ && $0 <= 20 {
printf "mv %s %03d\n", $0, $0+1
}' | sh
-q
(标准,但目前 busybox 不支持ls
)以确保每一行有一个文件名,即使存在名称中包含换行符的文件。LC_ALL=C
所以[0-9]
只匹配0123456789
.如果awk
是mawk
,请替换[0-9]{3}
为[0-9][0-9][0-9]
.
答案2
如果没有间隙,例如 logrotate 文件,那么 ls 可以为您完成工作,不需要 math / awk :
dest=021; ls -r|while read file; do mv $file $dest; dest=$file; done
如果 dest 不总是 021,那么类似 dest=$(printf "%03d" $(ls|wc -l))