8
5

More than 5 years have passed since last update.

同じファイルのgzipのmd5が異なる件

Last updated at Posted at 2018-04-20

はじめに

弊社のETLシステムを差し替えることになった際に、旧システムでETL処理した old.tsv.gz ファイルと新システムでETL処理したnew.tsv.gz ファイルが同じ内容になっているか確認する必要が生じました。(もちろんETL前は同じファイルです。)

しかし、md5sumを取ってみると、二つのファイルのハッシュ値が異なり、原因を調査したのでまとめます。

現象

$ ls -la old.tsv.gz new.tsv.gz
-rw-rw-r-- 1 user 425983  4月 20 14:36 old.tsv.gz
-rw-rw-r-- 1 user 425983  4月 20 14:36 new.tsv.gz

ファイルサイズが同じなので、内容も同じだという気分になってきます。
しかし、md5sumを計算してみると下記のように結果が異なります。

$ md5sum old.tsv.gz new.tsv.gz
0a4d0421dbaafc3e1c2f535ff8dfa7da  old.tsv.gz
6453d46698d5e237b7ae7d8686819171  new.tsv.gz

中身はきっと同じはず、、、、、
伸長(解答)したファイルの中身が一致していることを確認してみましょう。

$ gzip -d -c old.tsv.gz|md5sum
89257d0ba2167c69a7bc054ff68b4f48
$ gzip -d -c new.tsv.gz|md5sum
89257d0ba2167c69a7bc054ff68b4f48

原因

gzipコマンドのマニュアルを読んでみると下記のオプションの存在に気づきます。

-n --no-name
デフォルトでは、圧縮時に元ファイルの名前とタイムスタンプを保存させない。 (元の名前を切り詰める必要がある場合は、元の名前は必ず保存される。) 伸長時に、元のファイル名が存在しても復元せず (圧縮ファイル名から gzip 拡張子を取り除くだけとし)、 元ファイルのタイムスタンプが存在しても復元しない (圧縮ファイルからコピーする)。 このオプションは伸長時のデフォルトである。
-N --name
圧縮時に元ファイルの名前とタイムスタンプを保存する。 これがデフォルトである。 伸長時に元ファイルの名前とタイムスタンプが存在するなら復元する。 このオプションは、ファイル名の長さに制限があるシステムや、 ファイル転送の後にタイムスタンプが失われた場合に役立つ。

デフォルトのgzipコマンドで圧縮する際には、元ファイルの名前とタイムスタンプを保存します。
開発していた旧システムと新システムでは、保存されるタイミングが異なるため、タイムスタンプが異なっていたようです。

対策

用途によっては、元のファイルの名前、タイムスタンプを保存するのは不便だと感じます。
その際には、

gzip -n [file name]

としましょう。

また、pythonでgzipを作るときには、

with open('out.gz', 'wb') as f, gzip.GzipFile(filename='', mode='wb', fileobj=f, mtime=0.) as gz:
    gz.write(str.encode('sample content'))

とすると良いでしょう。

参考

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5