現場で使えるシェルスクリプト入門27:圧縮コマンドの使い分け(gzip/xz/zstd/zip)と圧縮ログの直接調査・一括処理スクリプト

シェルスクリプト IT

これまでの連載では、ファイル単位のアーカイブを作成する「tar + find(入門24)」、ディレクトリ間の差分を効率よく同期する「rsync(入門25)」、そしてブロックレベルでディスクイメージを保存する「dd + gzipパイプライン圧縮(入門26)」について解説してきました。

これらのバックアップや日常のサーバー運用において、ストレージ容量を節約しデータ転送を効率化するために欠かせないのが「データの圧縮・展開(解凍)技術」です。

入門24や入門26で活用した gzip は非常に信頼性が高く汎用性に優れたツールですが、実際の運用現場ではさらに以下のようなニーズに直面することがあります。

  • 用途に応じた圧縮形式の使い分け:長期保管向けに圧縮率を重視したい場合や、大容量データを短時間で高速に圧縮したい場合、あるいはWindows・Macユーザーへファイルを共有したい場合など、目的に合わせたツール選定。
  • 圧縮された過去ログの直接調査・集計:本番サーバーのディスクを圧迫せずに、.gz などに圧縮されたままの過去ログから特定のエラーを検索・集計する手法。
  • ログの圧縮退避と解凍による復元:ファイルシステムの容量を圧迫するログファイルを圧縮してサイズを縮小し、バックアップディレクトリへ移動・必要に応じて解凍して取り出す自動化処理。

今回は、Linux環境における主要な圧縮コマンド(gzip / xz / zstd / zip)の比較と使い分けから、圧縮ログを解凍せずに調査・集計する実践テクニック、そしてログを圧縮してバックアップディレクトリへ移動・解凍するスクリプトの実装までを分かりやすく解説します。

※本連載はロードマップ形式で順次公開しています。連載全体の流れや各回の一覧は「シェルスクリプト入門連載ロードマップ」からも確認できます。

主要な圧縮コマンドの比較と適材適所の使い分け

Linux環境では複数の圧縮コマンドが利用可能です。それぞれのアルゴリズムには「圧縮率」「処理速度」「互換性」のバランスに固有の強みがあり、保存期間や利用目的に応じて適材適所で使い分けることが推奨されます。

コマンド(拡張子)圧縮率圧縮・展開速度標準互換性主な用途・特徴
gzip(.gz)標準的速い(バランス良)非常に高い日常のログ保存、定期バックアップ、汎用スクリプト
xz(.xz)非常に高い圧縮は遅い / 展開は圧縮より速い高い長期保管用のコールドバックアップ、配布用アーカイブ
zstd(.zst)高い非常に速い普及が進行中大容量データの高速バックアップ、大量ログの高速圧縮
zip(.zip)標準的速いOS横断で高いWindows / macOS環境とのファイル共有・レポート配布

各ツールの特徴と運用現場での選定基準を詳しく見ていきましょう。

  • gzip(拡張子 .gz):多くのLinuxやUNIX環境に標準で搭載されているデファクトスタンダードな圧縮ツールです。圧縮率と処理速度のバランスが良く、CPUへの負荷も穏やかです。入門24の tar -czf や入門26のパイプライン圧縮のように、環境に依存しないポータブルなシェルスクリプトを作成する際の第一選択肢として広く活用されています。
  • xz(拡張子 .xz):LZMA2アルゴリズムを採用し、高い圧縮率を実現します。圧縮処理にはCPUリソースと時間を要しますが、展開(解凍)処理は圧縮より速いという特性があります。長期間保管してめったに書き換えないアーカイブや、ネットワーク帯域を節約したいソフトウェア配布パッケージ(Linuxカーネルのソース配布など)に適しています。
  • zstd / Zstandard(拡張子 .zst):Meta(旧Facebook)によって開発され、近年UbuntuやRed Hat系ディストリビューションのパッケージ管理・ファイルシステム等でも採用が進んでいるモダンな圧縮形式です。gzip と同等以上の圧縮率を維持しながら、圧縮・展開速度が大幅に速いという優れた特性を持ちます。大容量のデータベースダンプや日次の大量ログ圧縮など、バッチ処理の時間を短縮したい場面で力を発揮します。
  • zip / unzip(拡張子 .zip):gzip・xz・zstd は単体ではファイル圧縮のみを行い、複数ファイルをまとめる場合は通常 tar と組み合わせます。zip は「複数ファイルのアーカイブ(まとめ)と圧縮」を単体で行います。WindowsやmacOSの標準機能でそのまま展開できるため、シェルスクリプトで集計したCSVレポートやログ一式を他部門やクライアントへ共有・配布する用途で重宝されます。

なお、従来のLinux環境では bzip2(拡張子 .bz2)も広く使われてきました。現在新規にスクリプトを組む場合は gzip・xz・zstd のいずれかを選ぶケースが一般的ですが、既存のアーカイブを展開する場面に備えて拡張子とオプション(tar -xjvf など)を把握しておくと安心です。

単体圧縮・展開(解凍)の基本操作と元ファイルを消さないための注意点

シェルスクリプトでファイルを圧縮・展開(解凍)する際、コマンドのデフォルト挙動を正しく理解しておかないと、思わぬトラブルにつながることがあります。ここでは実践的な基本操作と注意点を整理します。

元ファイルが削除される仕様と -k(–keep)オプション

gzip や xz を引数なしで単体実行すると、圧縮完了後に元のファイルが自動的に削除され、圧縮ファイル(.gz や .xz)に置き換わるのが標準の仕様です(一方、zstd はデフォルトで元ファイルを残し、--rm を指定した際に元ファイルを削除する動作が一般的です)。

圧縮後も元のファイルをそのまま残しておきたい場合や、複数のコマンド間で挙動を統一したい場合は、-k(--keep)オプションを指定するか、-c(標準出力への書き出し)とリダイレクトを組み合わせる方法を推奨します。

# デフォルト動作:app.log が削除され、app.log.gz に置き換わる
gzip app.log

# -k オプション:元の app.log を残したまま app.log.gz を作成する
gzip -k app.log
xz -k app.log
zstd -k app.log

# -c オプション:標準出力を経由して別パスや別名で圧縮ファイルを作成する(元ファイルは残る)
gzip -c app.log > /backup/app.log.gz

圧縮レベルの指定(速度優先か容量優先か)

多くの圧縮コマンドでは、ハイフンに続けて数値を指定することで圧縮レベルを調整できます。

  • gzip / xz:-1(速度優先・低圧縮率)から -9(容量優先・高圧縮率)まで指定可能です(デフォルトは gzip が -6、xz も -6 が一般的です)。
  • zstd:-1 から -19(さらに高圧縮な --ultra -22)まで幅広く指定でき、デフォルトは -3 に設定されています。
# CPU負荷を抑えて素早く圧縮したい場合(レベル1)
gzip -1 -k large_dump.sql

# 時間がかかってもファイルサイズを極力小さくしたい場合(レベル9)
xz -9 -k archive_data.tar

tarと組み合わせる際の拡張子自動判別(tar -caf)

ディレクトリごとアーカイブして圧縮する tar コマンドでは、圧縮形式ごとに -z(gzip)、-J(xz)、--zstd(zstd)といった個別オプションが用意されています。

しかし、シェルスクリプト内で出力ファイル名の拡張子に応じてオプションを書き換えるのは手間がかかります。そこで便利なのが、出力ファイル名の拡張子から圧縮プログラムを自動判別してくれる -a(--auto-compress)オプションです。

# -a (--auto-compress) を使うと、拡張子(.gz / .xz / .zst)に応じて自動的に圧縮形式が選択される
tar -caf backup.tar.gz /var/www/html
tar -caf backup.tar.xz /var/www/html
tar -caf backup.tar.zst /var/www/html

# 展開(解凍)時は -a や -z 等を省略しても、GNU tar がヘッダや拡張子から自動判別して展開可能
tar -xf backup.tar.zst -C /tmp/restore/

tar -caf を覚えておくと、スクリプトの設定変数で拡張子を .tar.gz から .tar.zst へ変更するだけで圧縮方式をスムーズに切り替えられるため、保守性が向上します。

zipで覚えておきたい -r と -j オプションの使い分け

WindowsやMacのユーザー向けにシェルスクリプトで zip ファイルを作成する際は、以下の2つのオプションが頻繁に使われます。

  • -r(再帰的処理):指定したディレクトリ配下のサブディレクトリやファイルをまとめて圧縮します。
  • -j(junk paths:パス階層の除外):通常、zip /tmp/report.zip /var/log/myapp/summary.csv を実行すると、展開した際に var/log/myapp/summary.csv という深いフォルダ階層がそのまま再現されます。-j オプションを付けると、ディレクトリ階層を省いて summary.csv ファイル単体を直下に格納できるため、受け取る側にとって扱いやすいアーカイブになります。
# ディレクトリ構造を保ったまま丸ごとzip化する(-r)
zip -r /tmp/project_backup.zip /opt/myproject/

# 余計なディレクトリ階層(/var/log/myapp/)を含めず、ファイルだけを直下に格納する(-j)
zip -j /tmp/daily_reports.zip /var/log/myapp/report_20261029.csv /var/log/myapp/error_summary.txt

各コマンド(gzip / xz / zstd / zip)の展開(解凍)方法

圧縮したファイルを元の状態へ展開(解凍)する際も、コマンドによって「展開後に元の圧縮ファイルが削除されるか残るか」のデフォルト挙動が異なります。各形式の展開コマンドとよく使うオプションを整理しておきましょう。

圧縮形式主な展開(解凍)コマンドデフォルトの元ファイル(圧縮側)の扱い圧縮ファイルを残して展開する方法
.gz(gzip)gzip -d または gunzip展開後に削除されるgzip -dk(または gunzip -k)
.xz(xz)xz -d または unxz展開後に削除されるxz -dk(または unxz -k)
.zst(zstd)zstd -d または unzstd展開後もそのまま残る標準で残る(削除したい場合は --rm)
.zip(zip)unzip展開後もそのまま残る標準で残る(展開先指定は -d)
  • gzip(.gz)の展開:gzip -d ファイル名.gz または専用コマンドの gunzip ファイル名.gz を使用します。圧縮時と同様に、デフォルトでは展開が完了すると元の .gz ファイルは削除されます。元の .gz ファイルを残したまま展開したい場合は -k を組み合わせた gzip -dk を使うか、gzip -dc で標準出力から別パスへリダイレクトします。
  • xz(.xz)の展開:xz -d ファイル名.xz または unxz ファイル名.xz を使用します。こちらも元の .xz ファイルを残したい場合は xz -dk ファイル名.xz を指定します。
  • zstd(.zst)の展開:zstd -d ファイル名.zst または unzstd ファイル名.zst を使用します。zstd は展開時もデフォルトで元の .zst ファイルを削除せずに残す仕様となっています(展開後に元の .zst を自動削除したい場合は zstd -d --rm ファイル名.zst を指定します)。
  • zip(.zip)の展開:unzip ファイル名.zip を使用します(元の .zip ファイルはそのまま残ります)。カレントディレクトリが散らかるのを防ぐため、指定したディレクトリへ展開する -d オプションや、展開前に中身の一覧だけを確認する -l オプション、スクリプト内で確認プロンプトを出さずに上書き展開する -o オプションがよく使われます。
# --- 1. gzip (.gz) の展開(解凍) ---
gzip -d app.log.gz                        # 展開すると app.log.gz は消え、app.log になる
gunzip app.log.gz                         # gzip -d と同じ動作
gzip -dk app.log.gz                       # 元の app.log.gz を残したまま app.log を展開する
gzip -dc app.log.gz > /tmp/app.log        # 元の app.log.gz を残し、別ディレクトリへ展開する

# --- 2. xz (.xz) の展開(解凍) ---
xz -d archive.log.xz                      # 展開すると archive.log.xz は消え、archive.log になる
unxz archive.log.xz                       # xz -d と同じ動作
xz -dk archive.log.xz                     # 元の archive.log.xz を残したまま展開する

# --- 3. zstd (.zst) の展開(解凍) ---
zstd -d data.log.zst                      # 元の data.log.zst を残したまま data.log を展開する
unzstd data.log.zst                       # zstd -d と同じ動作
zstd -d --rm data.log.zst                 # 展開成功後に元の data.log.zst を削除する

# --- 4. zip (.zip) の展開(解凍) ---
unzip -l daily_reports.zip                # 展開せずに、zipファイル内のファイル一覧を事前確認する
unzip daily_reports.zip -d /tmp/restore/  # 指定したディレクトリ(/tmp/restore/)配下へ展開する
unzip -o daily_reports.zip -d /tmp/work/  # 既存ファイルがあっても確認なしで上書き(-o)展開する

圧縮ログを解凍せずに直接調査・集計する実践テクニック

運用現場で特に重要になるのが、「.gz や .zst に圧縮されて保管されている過去のログファイルを、ディスク上に解凍せずにそのまま調査・集計する」テクニックです。

本番環境で圧縮ログを安易に解凍しない方がよい理由

障害調査やアクセス解析のために、数GBある過去の圧縮ログ(例:access.log.202610.gz)を本番サーバー上でそのまま gunzip で解凍すると、以下のようなトラブルを招く恐れがあります。

  • ディスク容量の急激な圧迫:テキスト形式のログファイルは圧縮効率が高いため、解凍すると元の数倍〜十数倍のサイズに膨れ上がり、本番環境のディスク枯渇を引き起こすリスクがあります。
  • タイムスタンプの変化や再圧縮漏れ:解凍したファイルを調査後に再圧縮し忘れたり、ファイルの更新日時やパーミッションが変わってしまったりする原因になります。

Linuxには、圧縮ファイルをメモリ上で展開しながら標準出力や検索処理へ直接流し込む専用コマンド群が備わっています。

zgrep / zless / zdiff による直接検索・閲覧・比較

通常のテキストファイル(.log など)を調べる際は、grep(文字列検索)、less(スクロール閲覧)、diff(差分比較)、cat(中身出力)といった基本コマンドを使用します。しかし、.gz や .xz、.zst などに圧縮されたファイルはバイナリデータになっているため、通常の grep や less をそのまま実行しても文字化けしたり「バイナリファイルに一致しました」と表示されたりして、中身を正しく読むことができません。

そこでLinuxには、ディスク上に一時ファイルを作らず、メモリ上で自動的に展開(解凍)しながら検索や閲覧を行ってくれる専用コマンドが用意されています。

たとえば gzip(.gz)形式のファイルを調べる場合は、grep の先頭に z を付けた zgrep、less の先頭に z を付けた zless を使うことで、通常のテキストファイルを扱うときと同じオプション・操作感で圧縮ファイルを直接調査できます。圧縮形式ごとの対応コマンドは以下の通りです。

やりたい操作通常のテキスト用.gz(gzip)用.xz(xz)用.zst(zstd)用
文字列を検索するgrepzgrepxzgrepzstdgrep
ページ単位で閲覧するlesszlessxzlesszstdless
2ファイルの差分を比較するdiffzdiffxzdiffプロセス置換等を利用(※)
中身を標準出力へ流すcatzcat(gzip -dc)xzcat(xz -dc)zstdcat(zstd -dc)

※zstd 形式の2ファイルを解凍せずに差分比較したい場合は、Bashのプロセス置換を使って diff -u <(zstd -dc file1.zst) <(zstd -dc file2.zst) のように記述すると、一時ファイルを作らずに直接比較できます。

# 複数の圧縮ログ(.gz)を横断して、特定のエラー文字列を検索する
zgrep -i "timeout" /var/log/nginx/access.log.*.gz

# xz形式やzstd形式の圧縮ログを検索する場合
xzgrep -i "error" /var/log/archive/app_2026*.log.xz
zstdgrep "CRITICAL" /var/log/myapp/*.log.zst

# 巨大な圧縮ログを解凍せずにページャ(less)でそのまま閲覧する
zless /var/log/nginx/access.log.1.gz

# 圧縮された2つの設定バックアップやダンプファイルの差分を直接比較する
zdiff /backup/config_20261028.conf.gz /backup/config_20261029.conf.gz

zcat(gzip -dc)とパイプラインを組み合わせたログ集計

シェルスクリプトで過去の圧縮ログからデータを抽出・集計する際は、zcat(またはOS間の互換性が高い gzip -dc)を使って標準出力へ展開データを流し、パイプライン(|)で awk や sort、uniq 等へ繋ぐ手法が有効です。

# 過去の全圧縮アクセスログから、ステータスコード500番台のエラー発生元IP上位10件を集計する例
gzip -dc /var/log/nginx/access.log.*.gz \
  | awk '$9 ~ /^5[0-9][0-9]$/ {print $1}' \
  | sort \
  | uniq -c \
  | sort -nr \
  | head -n 10

この方法であれば、ディスク上に一時ファイルを作成することなく、複数日にわたる圧縮ログを高速かつ安全に集計できます。

なお、ここで使用している -dc オプションは、以下の2つのオプションを組み合わせた指定です。

  • -d(--decompress):圧縮されたデータを展開(解凍)するオプションです。
  • -c(--stdout):処理結果をディスク上のファイルに書き出すのではなく「標準出力(画面やパイプライン)」へ出力し、元の圧縮ファイルは消さずにそのまま残すオプションです。

この -d と -c を組み合わせることで、「元の .gz や .zst ファイルを変更・削除せず、ディスク上に解凍ファイルも作らないまま、展開されたテキストデータだけをそのまま次のコマンド(| awk ... など)へ流し込む」という安全なパイプライン処理が可能になります。

また、macOSなどのBSD系環境では zcat コマンドが .Z(compress形式)の拡張子を前提として動作し .gz でエラーになる場合がありますが、-dc オプションは gzip -dc・xz -dc・zstd -dc のいずれでも共通して同じ書き方で利用できるため、OS環境の違いや圧縮形式の違いに左右されにくく、シェルスクリプトの移植性と可読性が高まります。

実践:ログを圧縮してバックアップディレクトリへ移動するスクリプト

サーバーを運用していると、アプリケーションのログ置き場(例:/var/log/myapp)に非圧縮の .log ファイルが溜まり、「ファイルシステムの空き容量がいっぱいになってしまったため、ログを圧縮してサイズを小さくし、別ディスクのバックアップディレクトリ(例:/backup/logs)へ移動したい」という場面があります。

ここでは、圧縮と移動の流れが一目でわかるサンプルスクリプト(compress_and_move.sh)と、移動した圧縮ファイルを後から解凍して取り出す方法を見ていきましょう。

#!/bin/bash
# ログを圧縮してバックアップディレクトリへ移動するスクリプト

set -euo pipefail

LOG_DIR="/var/log/myapp"      # 圧縮元のログディレクトリ
BACKUP_DIR="/backup/logs"    # 圧縮後の移動先ディレクトリ

# 移動先ディレクトリが存在しない場合は作成する
mkdir -p "$BACKUP_DIR"

# LOG_DIR 内の .log ファイルを順番に圧縮して移動する
for log_file in "$LOG_DIR"/*.log; do
    # 該当する .log ファイルが存在しない場合はスキップ
    [ -f "$log_file" ] || continue

    echo "圧縮して移動中: $log_file"

    # 1. gzip で圧縮する(例: app.log が app.log.gz になりサイズが縮小される)
    gzip "$log_file"

    # 2. 生成された .gz ファイルをバックアップディレクトリへ移動して空き容量を確保する
    mv "${log_file}.gz" "$BACKUP_DIR/"
done

echo "ログの圧縮とバックアップ先への移動が完了しました。"

スクリプトの処理ポイント

  • *.log のみを指定して二重圧縮を防止:ループの対象を "$LOG_DIR"/*.log に限定しているため、非圧縮のログファイルだけが対象となり、すでに圧縮されたファイル(.gz)を誤って二重圧縮してしまう心配がありません。
  • gzip "$log_file" による圧縮:gzip を実行すると、元のファイル(例:/var/log/myapp/app.log)が圧縮され、末尾に .gz が付いたファイル(/var/log/myapp/app.log.gz)に置き換わります。テキストのログファイルであれば、これだけでファイルサイズが数分の一〜十分の一程度に縮小されます。
  • mv "${log_file}.gz" "$BACKUP_DIR/" による移動:圧縮によって生成された ${log_file}.gz をそのまま /backup/logs/ へ移動(退避)させることで、元の /var/log/myapp があるファイルシステムの空き容量をすぐに確保できます。

移動した圧縮ログを解凍して取り出す(復元する)には?

バックアップディレクトリ(/backup/logs)へ退避した圧縮ログを、後から調査や復元のために解凍して取り出したい場合は、次の2通りの方法が分かりやすくて便利です。

# 方法1:バックアップ先の .gz ファイルはそのまま残し、作業場所(/tmp 等)へ解凍して取り出す
gzip -dc /backup/logs/app.log.gz > /tmp/app.log

# 方法2:バックアップ先からファイルをコピーしてきて、gzip -d(または gunzip)で解凍する
cp /backup/logs/app.log.gz /tmp/
gzip -d /tmp/app.log.gz   # /tmp/app.log に解凍される

バックアップ先にある /backup/logs/app.log.gz に対して直接 gzip -d を実行するとバックアップ自体の圧縮が解けてしまうため、上記のように gzip -dc でリダイレクトするか、作業用ディレクトリへコピーしてから gzip -d で解凍しています。

大容量データを高速処理するマルチコア並列圧縮の活用

数十GB〜数百GBに及ぶデータベースのダンプファイルや巨大なアーカイブを圧縮する際、従来の gzip はシングルスレッド(CPUの1コアのみ)で動作するため、マルチコアサーバーであっても1コアだけが100%になり、処理完了まで長い時間がかかることがあります。

大容量データの圧縮時間を短縮したい場合は、マルチコアCPUを活かせる並列圧縮機能の活用が効果的です。

zstd や xz のマルチスレッドオプション(-T)

zstd や近年のバージョンの xz には、標準でマルチスレッド処理を行う -T(--threads)オプションが搭載されています。

# -T0 を指定すると、システムの利用可能なCPUコア数を自動検出して並列圧縮する
zstd -T0 -k huge_database.dump

# 本番サーバー等でCPUを使い切らないよう、使用するスレッド数を「2」に制限する例
zstd -T2 -k huge_database.dump
xz -T2 -k archive_data.tar

gzip互換の並列圧縮ツール「pigz」

出力形式を従来通り互換性の高い .gz(gzip形式)に保ったままマルチコアで高速化したい場合は、pigz(Parallel Implementation of GZip)というツールが利用されます(多くのディストリビューションで apt install pigz や dnf install pigz で導入可能です)。

# 4スレッド(-p 4)を指定して高速に .gz 圧縮を行う
pigz -p 4 -k huge_database.dump

# tar の圧縮プログラムとして pigz を指定し、高速に .tar.gz を作成する
tar --use-compress-program="pigz -p 2" -cf /backup/fast_backup.tar.gz /var/www/html

【運用上の注意点】:並列圧縮は非常に高速ですが、全コア(-T0 等)をフル稼働させると、稼働中のWebサーバーやデータベースの処理性能に一時的な影響を及ぼす可能性がありますのでご注意ください。

まとめ

今回は、Linuxとシェルスクリプトにおける圧縮コマンドの比較・使い分けから、圧縮ログの直接調査テクニック、そしてログを圧縮してバックアップ先へ移動・解凍するスクリプトまでを解説しました。

  • 圧縮形式の適材適所の使い分け:汎用性と互換性の gzip、長期保管向けの xz、高速・高圧縮を両立した zstd、他OSとの共有に適した zip を目的に応じて選択する。
  • 単体圧縮・展開時の元ファイル保護:元ファイルを残したい場合は -k(--keep)や -c オプションを活用し、tar 連携時は拡張子自動判別の tar -caf を使うとスクリプトの保守性が高まる。
  • 解凍しない直接調査・集計:zgrep や zless、gzip -dc からのパイプライン処理を活用することで、本番環境のディスクを圧迫せずに過去ログを迅速に解析できる。
  • 圧縮退避スクリプトとマルチコア活用:容量を圧迫する .log ファイルを gzip で圧縮してバックアップディレクトリへ移動(mv)することで空き容量を確保でき、大容量データにはスレッド数を調整した zstd -T2 や pigz を組み合わせることで効率的な運用が実現できる。

これまで学んだ tar・rsync・dd によるバックアップ技術と、今回の圧縮・直接解析テクニックを組み合わせることで、ストレージ容量とパフォーマンスの双方に配慮した実践的なシェルスクリプトを構築できるようになります。

現場で使えるシェルスクリプト入門 連載ナビゲーション

コメント

タイトルとURLをコピーしました