根据创建时间使用数字序列重命名目录中的所有文件

根据创建时间使用数字序列重命名目录中的所有文件

我正在尝试重命名目录中的所有文件,例如〜/folder/ contains(从最新到最旧):apple.foo,pie.foo,cookie.foo,melon.foo

使用固定前缀和数字 001 重命名它们最老的并增加到 999:

melon.foo >> object001.foo

cookie.foo >> object002.foo

馅饼.foo >> object003.foo

apple.foo >> object004.foo

有人知道如何实现这一目标吗?

答案1

使用zsh外壳:

counter=0

for name in $HOME/folder/*(.NDOm); do
    counter=$(( counter + 1 ))

    suffix=$name:e
    printf -v newname '%s/object%.3d%s' $name:h $counter ${suffix:+.$suffix}

    mv $name $newname
done

这会迭代~/folder目录中常规文件的所有名称,按上次修改的时间戳从最旧的到最新的。对于每个名称,使用当前名称的目录部分和计数器构造一个新名称。文件被重命名为这些新名称(无需确认,也无需检查名称冲突)。

printf -v newname调用将其输出“打印”到变量中newname。格式字符串将在三个位置输出一个以%.3d零填充的整数(例如001、等)。参数扩展将扩展到路径名的头/目录部分(与 相同)。023109$name:h$namedirname "$name"

$name:e扩展为原始文件名的“扩展名”(例如,foo如果当前文件是apple.foo),我们将其存储在suffix.${suffix:+.$suffix}如果有的话,我们会在文件扩展名前面添加一个点。

文件名通配模式末尾的 in 是一个通配符,它​​使前面的通配模式仅匹配常规文件.(.NDOm)andN使D模式的行为就好像shell中已设置nullgloband (如果没有匹配则展开为空,并在结果中包含隐藏名称)。对匹配的名称进行排序,以便最旧的(最近最少修改的)文件首先排序。dotglobbashOm

如果zsh不是您的登录 shell,则可以将其作为脚本运行。

$ zsh ./this-script

答案2

这是用 GNU 实用程序编写的版本bash,不需要解析ls,并且可以处理任何合法命名的文件(嵌入空格、标点符号、换行符等)

#!/bin/bash
k=0                                               # start at the beginning
find *.foo -type f -printf "%T@ %p\0" |           # list all the files with modification time
    sort -z |                                     # sort by increasing modification time
    cut -z -d' ' -f2- |                           # discard the time value leaving just the name
    while IFS= read -r -d '' file                 # now loop for each file...
    do
        ((++k))                                   # next count
        seq=$(printf "%03d" $k)                   # format the three-digit counter
        name="${file%.*}" ext="${file##*.}"       # split filename into name and extension
        echo will mv "$file" "$name.$seq.$ext"    # show what would happen without doing it
    done

echo will当您准备好mv执行命令时,删除。

例子

# preparation
for f in {melon,cookie,pie,apple}.foo; do touch "$f"; sleep 1; done

# list in order of modification time (oldest to newest)
ls -tr
melon.foo  cookie.foo  pie.foo  apple.foo

# run the script and observe the output
k=0; find *.foo -type f -printf "%T@ %p\0" | sort -z | cut -z -d' ' -f2- | while IFS= read -r -d '' file; do ((++k)); seq=$(printf "%03d" $k); name="${file%.*}" ext="${file##*.}"; echo mv "$file" "$name.$seq.$ext"; done

will mv melon.foo melon.001.foo
will mv cookie.foo cookie.002.foo
will mv pie.foo pie.003.foo
will mv apple.foo apple.004.foo

答案3

假设文件名不包含空格、制表符或换行符,使用单行 andbashawk会很简单:

ls -rt | awk -F "." '{print  $0 " object" sprintf("%03d",NR)  "." $NF }' | xargs -L 1 mv

该命令针对每一行xargs -l执行。mv在执行命令之前,请执行以下命令并检查目标文件名和源文件名是否正确:

ls -rt | awk -F "." '{print  $0 " object" sprintf("%03d",NR)  "." $NF }'

应该输出类似:

melon.foo object001.foo
cookie.foo object002.foo
pie.foo object003.foo
apple.foo object004.foo

相关内容