このコマンドを使用して、sha1sum
のランダムな文字でファイルの名前を変更し、すべてのファイルをサブディレクトリから現在のディレクトリに移動します。
for fname in `find . -type f`; do mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ').html; done
sha1sum
出力は、入力が一意である限り一意になります。 (非常に不運で、sha1sum
の衝突を見つけた場合を除きます)。
ユースケースについて:printf '%s' "$fname"
の代わりにecho "$fname"
を使用するのは良い習慣です。前者は、$fname
が-n
、または-e
、…の場合に機能します。 enzotib remark も参照してください。一見それを見逃しました。
また、あなたの動機は正確にはわかりませんが、ファイル名ではなくファイルの内容をsha1sum
に提供することを検討してください。このようにして、一意のコンテンツごとに一意のファイル名を取得します。
まず、いくつかのシェルが重要です。
for fname in `find …`
_を使用しないでください。ファイル名が壊れ、名前が長すぎるファイルが多すぎると失敗します(コマンドラインが長すぎるため)。代わりに_find -exec
_を使用してください。 find
によって実行されるコマンドでシェル拡張が必要なため、 シェルを呼び出す 。"$fname"
_、"$(echo …)"
)を二重引用符で囲む必要があります。echo
は、いくつかのシェルでバックスラッシュをマングルします(_-
_で始まるいくつかの引数もマングルしますが、すべての引数は_./
_で始まるため、ここでは問題になりません)。文字列を文字通りに出力する方法は、_printf "%s\n" "$fname"
_、または_printf "%s"
_ "$ fname"で、最後の改行を回避します。ここでは、ファイル名のハッシュとは対照的に、ファイル名のハッシュと最後の改行を取得する理由はありません。したがって、次のコマンドを取得します。
_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' _ {} +
_
この方法の問題は、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番目の質問については、ハッシュはハッシュする文字列によって完全に決定されます。したがって、_tweedledum/staple
_と_tweedledee/staple
_という2つのファイルがあり、各ディレクトリtweedledee
とtweedledum
からその名前変更手順を順番に実行すると、両方のディレクトリは次のようになります。 _1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html
_というファイル。別の名前を付けたい場合は、ディレクトリの名前など、ハッシュ化されたテキストにいくつかの識別可能なコンテンツを含める必要があります。
まず第一に私は代用することを提案します
for fname in `find . -type f`; do
と
find . -type f | while read -r fname; do
次に、sha1sumに関しては、「実質的に」一意である必要があります。つまり、かなり低い場合に同じチェックサムで異なるファイルを使用する可能性があり、安全に一意であると見なすことができます。