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

まず、いくつかのシェルの質問:

  • for fname in `find …`ファイル名が破損し、名前が長すぎるファイルが多すぎると(コマンドラインが長すぎるため)失敗するため、使用しないでください。代わりに使用してくださいfind -exec。実行されたコマンドにはシェル拡張が必要な​​のでfindシェル呼び出し
  • "$fname"コマンド置換と変数置換を二重引用符(、)で囲む必要があります"$(echo …)"
  • echo一部のシェルからバックスラッシュを分離します(で始まる引数も分離します-が、すべての引数がで始まるので問題ありません./)。文字列を文字通り印刷する 1 つの方法は、最後の改行文字を避けるためprintf "%s\n" "$fname"、または "$fname" です。printf "%s"ここでは、ファイル名のハッシュの代わりにファイル名のハッシュと最後の改行文字を使用する理由はありません。

だから我々は次のコマンドを取得します:

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

一度にフルネームのバッチに対してシェルを呼び出す方が少し高速です。

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

このアプローチの問題の1つは、ディレクトリの検索が完了する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/* .

それでは、主な質問に答えてみましょう。パスが異なる2つのファイルは、2つの異なるSHA-1ハッシュにマップされます。数学的に言えば、同じSHA-1ハッシュ値を持つ別の文字列があります(文字列は無限大ですが、ハッシュ数は有限であるため、これは明らかです)。しかし、実際にはこれを見つける方法を知っている人はいません。 SHA-1には既知の競合はありません。いつかSHA-1が破損する可能性があります。この場合、プログラムは悪意のある攻撃ではなく偶発的な衝突に対してのみ安全になります。このような場合(すぐには発生しない)、当時は安全と見なされるハッシュアルゴリズムにアップグレードする必要があります。

2番目の質問では、ハッシュ値は完全にハッシュされた文字列によって決まります。したがって、名前付きの2つのファイルがあり、各ディレクトリで名前変更プロセスを順番に実行するtweedledum/stapletweedledee/staple、両方のディレクトリに名前があります。ディレクトリ名などのテキストです。tweedledeetweedledum1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html

答え3

まず、交換を提案します

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

そして

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

次に、sha1sumは「ほぼ」固有でなければなりません。つまり、異なるファイルが同じチェックサムを持つ可能性が非常に低いため、一意であると安全に想定できます。

関連情報