自动递增文件名

ako*_*via 7 bash shell-script rename

我需要收集一些重复的文件并希望避免名称冲突。问题是,在清除文件之前,我的脚本的另一次执行可能会添加此文件集合,并且只想继续增加数字。

我决定使用一个简单的直到循环来增加数字。

until [[ ! -f ${PWD}/DUPES/${num}-$1 ]]; do
num=$((num +1))
done
mv --no-clobber $1 ${PWD}/DUPES/${num}-$1
Run Code Online (Sandbox Code Playgroud)

在一个极端的例子中,我无法想象超过 1k 的文件,所以我的问题是......

这是实现这一目标的非常低效的方法吗?我应该解析现有文件以获得从那里开始递增的最高前导数,还是对于我提出的极端示例可以这样吗?或者有更好的方法吗?

dha*_*hag 6

GNU mv 有一个--backup可能有用的选项。以下交互显示了目标存在时文件如何重命名:

$ touch a b c o
$ mv --backup=numbered --verbose a o
`a' -> `o' (backup: `o.~1~')
$ mv --backup=numbered --verbose b o
`b' -> `o' (backup: `o.~2~')
$ mv --backup=numbered --verbose c o
`c' -> `o' (backup: `o.~3~')
Run Code Online (Sandbox Code Playgroud)

在这个例子中,原始文件o已更名为o.~1~ao.~2~bo.~3~,和co。因此,这不会以与您发布的代码相同的方式重命名,但这可能是可以接受的,具体取决于您的确切需求。


mik*_*erv 5

你可以这样做:

set -C; num=0                                  ### set -o noclobber; init $num
[ -e "$1" ] &&                                 ### this needs to be true
until 2>&3 >"./DUPES/$((num+=1))-$1" &&        ### try to open() num+=1
      mv --  "$1"  "./DUPES/$num-$1"           ### if opened, mv over it
do :; done 3>/dev/null                         ### do nothing
Run Code Online (Sandbox Code Playgroud)

您将立即确保多个实例无法为任何给定文件保护相同的名称,并增加您的变量。

/dev/null<标准错误只是下降shell的投诉约存在的文件时,它会尝试做输出截断/重定向和发现现有的目标。虽然noclobber选项启用它不会覆盖另一个文件-它只会open()一个新的,除非你使用>|。所以你不需要它的抱怨,因为重点是增加现有文件,直到找到一个不存在的名称。

关于性能方面 -如果您不从零开始更好。或者,如果您试图弥补差额。我想以上可能会有所改进:

set -C; num=0                                  ### set -o noclobber; init $num
until 2>&3 >"./DUPES/$((num+=1))-$1"  &&       ### try to open() num+=1
      mv --  "$1"  "./DUPES/$num-$1"           ### if opened, mv over it
do    [ -e  "./DUPES/$((num*2))-$1" ] &&       ### halve fail distance
      num=$((num*2))                           ### up to a point of course
done  3>/dev/null                              ### done
Run Code Online (Sandbox Code Playgroud)

...但最多 1000 个,您可能不必太担心。我必须在几秒钟内通过随机名称达到 65k。

顺便说一句 - 你可能认为你可以:

>"./DUPES/$((num+=1))-$1" mv -- "$1" "./DUPES/$num-$1"
Run Code Online (Sandbox Code Playgroud)

...但它在bash外壳中不起作用。

num=0; echo >"/tmp/$((num+=1))" >&2 "$num"; echo "$num" /tmp/[01]
Run Code Online (Sandbox Code Playgroud)
0
1 /tmp/1
Run Code Online (Sandbox Code Playgroud)

无论出于何种原因bash,重定向的其他上下文中的分配都会发生 - 因此扩展以奇怪的顺序发生。所以你需要一个单独的简单命令来扩展正确的$num值,因为我在这里使用&&. 否则,虽然:

num=0; echo "$((num+=1))" "$num"
Run Code Online (Sandbox Code Playgroud)
1 1
Run Code Online (Sandbox Code Playgroud)