根据排名编号重命名文件?

根据排名编号重命名文件?

我对脚本编写(bash shell)非常陌生,我无法弄清楚我试图完成的这项任务的逻辑。

我有一个文件夹,其文件名如下(例如):

PIC-100
PIC-1
PIC-23
PIC-5

我希望能够从他们的文件名中获取数字,按从最低到最高的顺序对它们进行排名,然后根据它们在排名列表中的位置对其进行重命名。

例如,它们将被重命名为:

PIC-100 --> PIC-4
PIC-1   --> PIC-1
PIC-23  --> PIC-3
PIC-5   --> PIC-2

谢谢大家。

答案1

我将向您展示如何逐步解决这个问题。首先,让我们创建一些测试数据:

mkdir /tmp/blah && cd /tmp/blah
for f in 1 90 $RANDOM $RANDOM $RANDOM; do touch PIC-$f; done
ls

文件应按名称排序,但我们希望它们按数字排序。该命令sort可以帮助解决这个问题:

ls | sort -V

-V意味着“版本化排序”,这适合您的情况。对于其他选项,请参阅man sort

现在进行重命名。有很多方法可以做到这一点,但我将循环遍历排序列表的输出。我们需要一个变量和一个循环:

counter=1 ls PIC-* | sort -V | while read fname; do
    echo mv -i "$fname" NEWPIC-$counter
    let counter+=1
done

这里发生了很多事情,所以我将详细解释 - 从安全开始。首先,备份您的文件在继续之前 - 循环很容易出错并导致糟糕的一天。这是备份所有内容的命令:

mkdir backup; cp PIC* backup

如果这个循环出错,我们可能会弄得一团糟,所以我想在运行它之前看看会发生什么。注意echo?这将打印出预期的命令而不是运行它们。您可以删除echo或仅复制粘贴输出以“真正”运行命令

接下来,我就开始mv -i争取更名。如果我要覆盖某些内容,这会提示 - 无论如何,那时一切都已经变成了梨形,但至少我会知道。

第三,请注意我将其重命名PIC-xxxNEWPIC-xxx。这是真的很重要因为在某些情况下我可能会意外地将 PIC-3 重命名为 PIC-2(例如,如果由于某种原因存在 PIC-2.5)。我们可以NEW稍后清理该部分。

另外,我用 启动命令counter=1 ls | sort -V | ...。通过设置变量命令,当我忘记在测试运行之间设置它时,我避免看到“奇怪”的行为 - 目标文件名将以NEWPIC-6或其他内容开头,而不是NEWPIC-1.这是你犯了几次错误后养成的习惯之一:)

现在来说说循环本身。

  • while read fname说“每次看到一行输入时,将该行放入变量中fname并运行下一部分
  • do .. done包围您要为每一行运行的代码
  • echo mv -i "$fname" NEWPIC-$counter打印出您要运行的命令
  • let counter+=1增加你的计数器变量。如果您忘记了这一点,您最终会调用一个文件NEWPIC-1,而所有其他文件都会消失。这就是我们有备份的原因:)

最后,这里有一个小技巧可以NEW从文件名的开头删除它:

for fname in NEWPIC-*; do echo mv $fname ${fname#NEW}; done

echo和以前一样,当您对输出满意时删除。

答案2

这个带注释的 shell 脚本可以做你想要的事情。分号表示顺序执行命令,竖线表示管道,井号开始注释,“do-done”对是“while”中包含的循环

n=1            ; # initialize counter
ls             | # list current working directory
sort -V        | # sort (thanks to dwurf for the flag, but this isn't in POSIX standard yet)
while read f   ; do
mv "$f" PIC-$n ; # rename file 
n=$((n+1))     ; # counter increment. 
done

答案3

使用zsh外壳:

tmpdir=$(mktemp -d)

n=1
for name in PIC-*(.n); do
    mv $name $tmpdir/PIC-$(( n++ ))
done

mv $tmpdir/PIC-* .
rmdir $tmpdir

这会将当前目录中名称匹配的所有常规文件移动+重命名PIC-*到临时目录中。文件根据文件名中的数字按排序的数字顺序移动(这是glob 限定符n中的(.n)作用;.仅选择常规文件)。对于每个文件,该文件被重命名为PIC-n其中n是一个计数器。

移动并重命名所有文件后,它们将移回当前目录,并删除临时目录。

使用临时目录作为暂存区是为了避免名称冲突。

如果有数千个文件,则mv可能需要在循环中执行第二个文件,以避免“参数列表太长”错误:

# first loop as before, then...

for name in $tmpdir/PIC-*; do
    mv $name .
done

rmdir $tmpdir

如果您在末尾使用cp文件而不是文件,则以“相反顺序”执行操作还将在临时目录中为您提供文件的原始名称备份:mv

tmpdir=$(mktemp -d)

mv PIC-*(.) $tmpdir

n=1
for name in $tmpdir/PIC-*(n); do
    # change "mv" to "cp" (and remove "rmdir" below)
    # to leave a copy in the temporary directory
    mv $name PIC-$(( n++ ))
done

rmdir $tmpdir

相关内容