为移动的文件生成新名称以防止覆盖?

kyl*_*e k 8 filenames busybox rename files

如果存在同名的现有文件,如何为文件生成新名称?在桌面环境中,我在文件名末尾附加一个数字会生成一个新名称,但是如何从命令行完成此操作?

我正在使用带有 Busybox 的 Android 操作系统。

Jos*_* R. 5

假设你有一个 POSIX shell,你可以这样做:

mv() {
        eval "DEST=\${$#}" #The destination is the last positional parameter
        if [ -e "$DEST" ] && ! [ -d "$DEST" ];then
                PREFIX=${DEST%.*}
                COUNT=1
                EXT=${DEST##*.}
                args= i=1
                while [ $i -lt $# ]; do args="$args \"\${$i}\"" i=$((i+1)); done
                DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                while [ -e "$DEST" ];do
                    COUNT=$((COUNT+1))
                    DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                done
                eval "command mv $args \"\$DEST\""
        else
                command mv "$@"
        fi
}
Run Code Online (Sandbox Code Playgroud)

如何使用这个

这是一个函数,因此将其保存在您的文件中~/.bashrc并像平常一样调用它mv

这是做什么的

  • 将原始mv可执行文件的路径存储在MV变量中
  • 获取调用它的最后一个参数到变量中 DEST
  • 如果DEST存在且不是目录,则此函数假定您的重命名试图破坏文件
  • 然后它提取最终名称的前缀(在 final 之前的任何内容.,标记扩展名)、扩展名(在 final 之后的任何内容).)、计数(如果有的话;在 final 之后的前缀中的任何内容-)。
  • 如果没有找到计数,则提取的计数设置为零,否则设置为在上一步中找到的计数。
  • 当前计数递增
  • 然后,该函数使用所有原始参数(开关 + 文件名)减去最后一个参数调用自身,并添加新文件名而不是原始调用中的最后一个参数。新名称是旧名称,但在扩展名之前添加了一个 3 位计数器(带零填充)。
  • 该函数是递归的,因为如果您说它mv a.txt b.txt会先尝试mv a.txt b-001.txt. 下一个mv调用也必须是函数本身,因为如果b-001.txt也存在,我们希望不断增加计数器,直到找到不存在的新文件名。
  • 如果最后一个参数不存在或者是一个目录,则原始mv可执行文件将使用您的原始参数调用。

注意事项

  • 您可以重复尝试破坏现有文件的次数取决于计数器的长度(在这种情况下为 999 次)。您可以选择包含文件系统上的 inode 限制的多个数字,以确保只要您能够创建文件,这将有效。
  • 如果您尝试破坏名称类似于 的文件foo-001.txt,它将被移动到foo-001-001.txt.

笔记

  • 要更改命名模式,3请将printf语句中的更改为您喜欢的任何内容。
  • 此代码已经过测试
  • 这是非常简单的,我相信会有一些极端情况下它会惨遭失败。如果您发现任何问题,我很乐意尝试为您修复它们。同时,不要在生产机器上尝试这个。