
このコマンドを使用して、任意の文字でファイル名を変更し、sha1sum
すべてのファイルをサブディレクトリから現在のディレクトリに移動します。
for fname in `find . -type f`; do mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ').html; done
- しかし、問題はこれが一意のファイル名を生成することです。 sha1sumによって生成された名前が一意でない可能性があること(複数回生成される)が心配です。
- 上記のコマンドを実行してから別のディレクトリから別のコマンドを実行すると、各ファイルに固有のファイル名が生成されますか?
答え1
sha1sum
入力が一意である限り、出力も一意です。 (とても運が悪く、sha1sum
衝突が発生しない限り)
ユースケースでは、printf '%s' "$fname"
代わりに使用するのが良い習慣です。echo "$fname"
前者は$fname
is -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/staple
とtweedledee/staple
、両方のディレクトリに名前があります。ディレクトリ名などのテキストです。tweedledee
tweedledum
1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html
答え3
まず、交換を提案します
for fname in `find . -type f`; do
そして
find . -type f | while read -r fname; do
次に、sha1sumは「ほぼ」固有でなければなりません。つまり、異なるファイルが同じチェックサムを持つ可能性が非常に低いため、一意であると安全に想定できます。