大量に保存した画像ファイルなどの重複潰しも兼ねて、ファイル名を MD5 ハッシュ値にリネームして保存しています。
まったく同一のファイルであれば、ハッシュ値が同一になりますので、ファイル名が同一になります。上のスクリプト「hashmv」ではリネーム時に同一ファイルを上書きしますので、結果、重複ファイルを除去することができます。
実行イメージ
$ hashmv foobar.jpg
foobar.jpg -> ./d41d8cd98f00b204e9800998ecf8427e.jpg
hashmv では、32 文字のハッシュ値のそのままファイル名に変換しているので、ちょっと長いなと思いました。md5sum
のオプションを見ても、もうちょっとコンパクトな出力を得るオプションが見当たらなかったので、車輪の再発明上等でシェルスクリプトを書いてみました。
#!bash
function compress_hash()
{
echo $2 | sed \
-e 's/aaa*/A/g' \
-e 's/abb*/B/g' \
-e 's/acc*/C/g' \
-e 's/add*/D/g' \
-e 's/aee*/E/g' \
-e 's/aff*/F/g' \
-e 's/baa*/G/g' -e 's/ecc*/g/g' \
-e 's/bbb*/H/g' -e 's/edd*/h/g' \
-e 's/bcc*/I/g' -e 's/eee*/i/g' \
-e 's/bdd*/J/g' -e 's/eff*/j/g' \
-e 's/bee*/K/g' -e 's/faa*/k/g' \
-e 's/bff*/L/g' -e 's/fbb*/l/g' \
-e 's/caa*/N/g' -e 's/fcc*/n/g' \
-e 's/cbb*/M/g' -e 's/fdd*/m/g' \
-e 's/ccc*/O/g' -e 's/fee*/o/g' \
-e 's/cdd*/P/g' -e 's/fff*/p/g' \
-e 's/cee*/Q/g' -e 's/0[0-9][0-9]*/q/g' \
-e 's/cff*/R/g' -e 's/1[0-9][0-9]*/r/g' \
-e 's/daa*/S/g' -e 's/2[0-9][0-9]*/s/g' \
-e 's/dbb*/T/g' -e 's/3[0-9][0-9]*/t/g' \
-e 's/dcc*/U/g' -e 's/4[0-9][0-9]*/u/g' \
-e 's/ddd*/V/g' -e 's/5[0-9][0-9]*/v/g' \
-e 's/dee*/W/g' -e 's/6[0-9][0-9]*/w/g' \
-e 's/dff*/X/g' -e 's/7[0-9][0-9]*/x/g' \
-e 's/eaa*/Y/g' -e 's/8[0-9][0-9]*/y/g' \
-e 's/ebb*/Z/g' -e 's/9[0-9][0-9]*/z/g' \
| cut -c -$1
}
for hashstr in $@
do
compress_hash 6 $hashstr
done
元のハッシュ値は [a-f0-9]
の文字集合ですが、パターンマッチングによって [a-fA-Z0-9]
の文字集合に置き替え、桁数を落としています。見たとおり、ある一定のパターンの繰り返しを単一文字に置き換えているので、上のスクリプトでは元ハッシュ値に対する可逆性はありません。さらに、破壊的に圧縮したハッシュ値をcut
で任意の桁数に切り落としています。
次に、評価用のコードを示します。
while :
do
hash=$(date +%s | md5sum | cut -f 1 -d ' ')
compress_hash 6 $hash
sleep 1
done
1秒おきに、UNIX タイム文字列を変換して印字する評価コードです。実行すると
dFc7wa
vqA5cx
rc1a1d
ucufyV
1d2b8c
qm9Le4
6sqc5c
atavIr
7bqc5r
3auf7b
....
のように、6 桁の圧縮されたハッシュ値が出てきます。
短縮 URL などの用途に代表されるように、URL セーフな文字列で桁数を抑えつつもある程度のパターン数は稼ぎたい場合に有効かもしれません。なお、元のハッシュ値は基数が a-z0-f
の 16 ですが、これは a-zA-Z0-9
の 62 となる為、6 桁でも約 568 億パターンも稼ぐことが可能です。
# 62^10 = 839299365868340224 (約84京パターン)
# 62^9 = 13537086546263552 (約1.3京パターン)
# 62^8 = 218340105584896 (約218兆パターン)
# 62^7 = 3521614606208 (約3.5兆パターン)
# 62^6 = 56800235584 (約568億パターン)
# 62^5 = 916132832 (約9億パターン)
# 62^4 = 14776336 (約1477万パターン)
6 桁なら長くなく、覚えられない長さではないし、1/568億の確率で衝突するくらいの強さは持ってますので、ファイル管理には十分だと思いました。
なお、a-zA-Z0-9
の文字集合に加えて記号 /+=
を許可する場合は、上のようなスクリプトではなくハッシュ値をそのまま base64 エンコードした方が手っ取り早いです。