使用 sha1sum 中的随机字符重命名文件。名字会是独一无二的吗?

使用 sha1sum 中的随机字符重命名文件。名字会是独一无二的吗?

我使用此命令来重命名带有随机字符的文件,sha1sum并将所有文件从子目录移动到当前目录:

for fname in `find . -type f`; do mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ').html; done
  1. 但问题是:它会创建唯一的文件名吗?我担心 sha1sum 生成的名称可能不唯一(生成两次或多次)。
  2. 如果我运行上述命令,然后在另一个目录中运行另一个命令,它会为每个文件生成唯一的文件名吗?

答案1

sha1sum只要输入是唯一的,输出就是唯一的。 (除非你非常不幸并且发现了一些sha1sum碰撞)。

至于您的用例:使用printf '%s' "$fname"代替是一个好习惯echo "$fname",前者在$fnameis -n、或-e、... 时有效。另请参阅恩佐替布备注,我第一眼就错过了。

另外,我不确定您的动机是什么,但您可以考虑提供sha1sum文件内容而不是文件名。这样,您将为每个独特的内容获得唯一的文件名。

答案2

首先,一些 shell 问题:

  • 不要使用for fname in `find …`,因为如果有太多名称太长的文件,这会破坏文件名并且会失败(因为命令行太长)。代替使用find -exec。由于您需要在执行的命令中进行 shell 扩展find调用外壳程序
  • 您需要用双引号括起命令替换和变量替换 ( "$fname", "$(echo …)")。
  • echo破坏一些 shell 上的反斜杠(它还会破坏一些以 开头的参数-,但这不是问题,因为所有参数都以 开头./)。按字面意思打印任何字符串的一种方法是printf "%s\n" "$fname", 或printf "%s""$fname" 以避免最后的换行符。在这里,我认为没有理由采用文件名的哈希值加上最后的换行符,而不是文件名的哈希值。

所以我们得到这个命令:

find . -type f -exec sh -c 'mv "$0" "$(printf "%s" "$0" | sha1sum | cut -f1 -d" ").html' {} \;

一次为整批名称调用 shell 会稍微快一些。

find . -type f -exec sh -c 'for fname; do mv "$fname" "$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +

此方法的一个问题是,如果在完成遍历目录mv之前开始执行操作find,则已移动的文件可能会被mv.这不是您的命令的问题,因为它会find在开始移动文件之前等待完成。因此,将重命名的文件放在不同的目录层次结构中。这将解决您建议的命令也存在的另一个问题,即mv可能会覆盖恰好被称为<sha1sum>.html.

mkdir ../staging
find . -type f -exec sh -c 'for fname; do mv "$fname" ../staging/"$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +
find . -depth \! -name "." -type d -exec rmdir {} +
mv ../staging/* .

现在回答您的主要问题:具有不同路径的两个文件将映射到两个不同的 SHA-1 哈希值。从数学上来说,存在具有相同 SHA-1 哈希值的不同字符串(这是显而易见的,因为字符串有无限多个,但哈希值只有有限个)。然而,实际上,没有人知道如何找到它们:SHA-1 没有已知的冲突。未来的某一天,SHA-1 可能会被破坏,在这种情况下,您的程序只能安全地防止意外冲突,而不能防止恶意攻击。如果发生这种情况(不会很快发生),您应该升级到当时被认为是安全的哈希算法。

至于你的第二个问题:哈希值完全由你哈希的字符串决定。因此,如果您有两个名为 和 的文件tweedledum/staple,并且依次从每个目录和tweedledee/staple运行该重命名过程,那么这两个目录最终都会生成一个名为.如果想要有不同的名称,则需要在散列文本中放入一些区分的内容,例如目录的名称。tweedledeetweedledum1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html

答案3

首先我建议替换

for fname in `find . -type f`; do

find . -type f | while read -r fname; do

接下来,关于 sha1sum,它应该是“几乎”唯一的,这意味着不同文件具有相同校验和的概率相当低,这样您就可以安全地假设它是唯一的。

相关内容