重命名多个文件递增顺序

重命名多个文件递增顺序

我有以下文件

SSt12.precip.374.sub.climatology.ctl
SSt12.precip.2874.sub.climatology.ctl
SSt12.precip.3764.sub.climatology.ctl
SSt12.precip.6774.sub.climatology.ctl

我想将文件重命名为

SSt12.precip.1.sub.climatology.ctl
SSt12.precip.2.sub.climatology.ctl
SSt12.precip.3.sub.climatology.ctl
SSt12.precip.4.sub.climatology.ctl

答案1

zsh

$ autoload zmv
$ n=0; zmv -n '(*.)<->(*.ctl)(#qn)' '$1$[++n]$2'
mv -- SSt12.precip.374.sub.climatology.ctl SSt12.precip.1.sub.climatology.ctl
mv -- SSt12.precip.2874.sub.climatology.ctl SSt12.precip.2.sub.climatology.ctl
mv -- SSt12.precip.3764.sub.climatology.ctl SSt12.precip.3.sub.climatology.ctl
mv -- SSt12.precip.6774.sub.climatology.ctl SSt12.precip.4.sub.climatology.ctl

(再次执行此操作,而不-n实际执行重命名)。

使用 GNU 工具并假设文件名不包含换行符,您可以这样做:

ls -v | awk -F. -vOFS=. -vORS='\0' '/\.ctl$/{print;$3=++n;print}' |
  xargs -r0n2 echo mv --

(删除echo以实际进行重命名)

答案2

printf 'cp SSt12.precip.374.sub.climatology.ctl \
   SSt12.precip.%d.sub.climatology.ctl\n' $(seq 5) | 
. /dev/stdin

显然你的意思是改名- 很抱歉对于这个误会。

但如果确实如此...说 374 - 378 ...

printf 'n=%d ; mv SSt12.precip.$((373+n)).sub.climatology.ctl \
   SSt12.precip.${n}.sub.climatology.ctl\n' $(seq 5) | 
. /dev/stdin

关于您上面的评论 - 假设它们位于同一目录中并且它们是唯一匹配的文件SSt12.precip.*.sub.climatology.ctl

set -- SSt12.precip.*[67]4.sub.climatology.ctl
printf 'echo mv %s SSt12.precip.$((n=n+1)).sub.climatology.ctl\n' "$@" | 
    . /dev/stdin

我已经用echo上面的方法削弱了它,这样你就不会因为我的帐户而感到遗憾。在目前的形式下,它只会显示它想要做什么。删除后echo,文件就归您所有,可以移动或丢失。

请参阅下面 Stephane 的评论,了解有关正确排序顺序的说明 - 他是对的。

答案3

假设您实际上有多个文件而不是同一个文件,因此您想要重命名每个文件,您可以这样做:

for i in *ctl; do echo "$i"; done | 
    sort -t'.' -nk3 | 
        awk -F'.' -v OFS='.' '{printf "mv %s ", $0; $3=NR;print}' |
            sh

上面假设您的文件名与您在问题中显示的完全相同。它们都有一个数字作为 3 点分隔的字段,并且都以 结尾ctl

答案4

第一个障碍是以正确的顺序获取文件。通配符模式SSt12.precip.*.sub.climatology.ctl按字典顺序而不是数字顺序扩展文件名,因此它将文件按 2874、374、3764、6774 的顺序排列。

在 zsh 中,这很容易解决,这要归功于n 全局限定符( SSt12.precip.*.sub.climatology.ctl(n))。在其他 shell 中,这需要更多工作。您可以提取数字并对它们进行排序。只要文件名不包含任何换行符,这里就有一种方法。我通过剥离前两个点分隔的段,然后剥离除第一个点分隔的段之外的所有段来提取数字。

number=1
for x in SSt12.precip.*.sub.climatology.ctl; do
  number="${x#*.*.}"; number="${number%%.*}"
  printf "%d %s\n" "$number" "$x"
done | sort -k1,1n |
while IFS= read -r filename; do
  filename=${filename#* }
  suffix=${filename#*.*.*.}
  prefix=${filename%.*."$suffix"}
  mv -- "$filename" "$prefix.$number.$suffix"
  number=$((number+1))
done

相关内容