这是 Terdon 建议的一种将文件重命名为随机文件名的方法。这种方法的优点是它可以自动解决文件名冲突:
randomname() { base64 < /dev/urandom | tr -dC a-z0-9 | head -c4; }
for f in *.png; do
newName=$(randomname).png
while [ -e "$newName" ]; do
newName=$(randomname).png
done
mv -- "$f" "$newName"
done
这是另一种方法,使用zmv
.优点是可以用它批量重命名不同扩展名的文件:
zmv '*(.*)' '${(Lr:8:)$(uuidgen)}$1'
我想修改第二种方法,以便它能够像第一种方法一样自动解析文件名冲突,但我不明白如何实现。有人可以帮忙吗?
如果您只需要处理多个扩展,可以通过第一种方法中循环的变体来完成。这使用
:e
扩展修饰符将原始文件扩展名添加到新名称(以及一些zsh
-ism 以避免重复新名称代码):使用 时,下一次扩展(呼叫和分机)
newName::=
的结果将被分配给该变量。这只是一个空的循环体,因为我们需要的一切都在条件中。uuidgen
newName
{}
[[ ]]
使用类似的方法
zmv
:这演示了该
-n
标志,这是使用的原因之一zmv
- 它会打印不执行任何操作会发生的情况,这对于调试非常有用。删除-n
来实际重命名文件。警告:如果与文件系统上已有的文件发生冲突,这将自动转到下一个名称。但是,如果在一次调用uuidgen
期间生成两个相同的名称的可能性非常小,则将检测到潜在的冲突并退出而不重命名任何文件。zmv
zmv
纯粹为了娱乐,这里的版本避免了几乎所有外部依赖,并使用完全用
zsh
.它基于我不久前所做的一些实验:发生碰撞的概率很低。所以只希望没有碰撞,如果有的话再试一次。您可以检测冲突,因为 zmv 有专门的错误消息。
尝试次数的限制是为了防止出现错误且重命名很可能发生冲突,以及防止出现其他错误但字符串
both map to
出现在文件名中。这里有一些其他方法,它们比给定问题所需的更复杂,但演示了 zmv 在其舒适区之外的使用。 zmv 接口主要设计用于计算每个文件名的替换的方法独立于其他文件名的情况。但是,有一些技巧可以在替换名称之间建立依赖关系。
一件简单的事情就是在替代品中注入一个计数器。您可以在算术表达式中递增计数器。这从一个文件名一直保留到下一个文件名,因为替换表达式不在子 shell 中计算。
在替换表达式中运行任意代码很容易:它只是命令替换。但这会将代码放在子 shell 中,因此您无法在调用之间保持任意状态。然而,对于这个特定的任务,您所需要的只是 zmv 维护的内部变量
from
来跟踪新文件名。我假设文件名不以换行符结尾。该变量没有记录,尽管它自引入
from
以来就一直存在。zmv
如果我们不想依赖它怎么办?那么就比较复杂了,但是我们仍然可以通过${VAR::=VALUE}
参数替换来更新状态。下面的代码用作n
新名称的临时变量,并seen[$n]
跟踪已分配的新文件名。${…:+}
隐藏嵌套参数扩展的结果。一种不太直观但代码更简单的方法是在进行模式匹配后立即准备替换文本。在该模式中,您可以使用
e
glob 限定符来运行任意代码。