gzipはデフォルトで圧縮と同時に元ファイルを削除する。元ファイルを残したまま圧縮ファイルだけを作りたい場合は-k(--keep)オプションを使う。

gzipは元ファイルを削除する

gzipにファイルを指定すると、.gz拡張子の圧縮ファイルが作られると同時に元ファイルは削除される。

$ ls -l app.log
-rw-r--r-- 1 root root 23033 Aug 16 22:57 app.log

$ gzip app.log
$ ls -l app.log*
-rw-r--r-- 1 root root 160 Aug 16 22:57 app.log.gz

app.logは残らずapp.log.gzだけになる。ログを圧縮して保存しつつ元ファイルも参照したい場合など、削除されると困る場面がある。

-kオプションで元ファイルを残す

-k(--keep)を付けると、圧縮ファイルを作成したあとも元ファイルが削除されずに残る。

$ ls -l app.log
-rw-r--r-- 1 root root 23033 Aug 16 22:58 app.log

$ gzip -k app.log
$ ls -l app.log*
-rw-r--r-- 1 root root 23033 Aug 16 22:58 app.log
-rw-r--r-- 1 root root   157 Aug 16 22:58 app.log.gz

app.logapp.log.gzの両方が残る。

既に.gzが存在する場合は上書きされない

-kで圧縮したとき、同名の.gzファイルが既に存在すると上書きされずエラーになる。

$ gzip -k app.log
gzip: app.log.gz already exists;	not overwritten

再実行して圧縮ファイルを更新したい場合は-f(--force)を組み合わせる。

$ gzip -kf app.log
$ ls -l app.log*
-rw-r--r-- 1 root root 23033 Aug 16 22:58 app.log
-rw-r--r-- 1 root root   157 Aug 16 22:58 app.log.gz

-fを付けなければ確認なしで上書きされることはないため、意図せず圧縮ファイルを消してしまう事故を防げる。

gunzipでも-kが使える

展開するgunzip(gzip -dと同等)にも-kがあり、展開後に.gzファイルを残せる。

$ ls app.log.gz
app.log.gz

$ gunzip -k app.log.gz
$ ls -l app.log*
-rw-r--r-- 1 root root 23033 Aug 16 22:58 app.log
-rw-r--r-- 1 root root   157 Aug 16 22:58 app.log.gz

-kを付けなければapp.log.gzは展開後に削除され、app.logだけが残る。

-cで標準出力に書き出す方法との違い

元ファイルを残す方法として-c(--stdout)を使い、リダイレクトで圧縮ファイルを作る方法もよく使われる。

$ gzip -c app.log > app.log.gz
$ ls -l app.log*
-rw-r--r-- 1 root root 23033 Aug 16 22:58 app.log
-rw-r--r-- 1 root root   154 Aug 16 22:58 app.log.gz

結果としてはどちらも元ファイルと圧縮ファイルの両方が残るが、動作は異なる。

-k-c
出力先元ファイル名.gzを自動生成標準出力へ書き出す(リダイレクトが必要)
出力ファイル名の変更不可リダイレクト先で自由に指定できる
既存の出力ファイルがある場合確認してエラーになる無条件に上書きされる

-cはリダイレクト先を自分で指定できるため、日付を付けたファイル名で保存したい場合などに向いている。

$ gzip -c app.log > /tmp/app.log.$(date +%Y%m%d).gz

一方-cはシェルのリダイレクトによる上書きのため、既存ファイルがあっても確認なく上書きされる。誤った上書きを避けたい場合は-kの方が安全である。

ログのバックアップとしての利用例

ログファイルを消さずに圧縮だけ残す場合の典型的な使い方は次のとおりである。

$ gzip -k /var/log/myapp/app.log

gzip -kのあとに元ファイルの中身だけを空にすると、圧縮によるバックアップを残しつつディスク容量を解放できる。

$ gzip -k app.log
$ truncate -s 0 app.log

truncate -s 0の詳細は【truncate】truncate -s 0でログをクリアする を参照。

参考