Linux - ファイルの圧縮と解凍方法（六種類）

# Linux圧縮と解凍

主に単一ファイルの圧縮を対象とし、ディレクトリではありません。

## 1.1 compressとuncompress

このツールはncompressパッケージから来ており、現在はあまり使用されていません。
対応するファイルは `.Z` 拡張子を持ちます。
フォーマット:
```
compress [OPTION]... [FILE]...
uncompress [OPTION]... [FILE]...
```

### よく使うオプション
- `-d` : 解凍、uncompressと同じ
- `-c` : 結果を標準出力に出力し、元のファイルは削除しない
- `-f` : 既存の対象ファイルを上書きする
- `-v` : 処理を表示する
- `-r` : ディレクトリ内のすべてのファイルを再帰的に圧縮する

例：

```shell
[root@rocky86 0726]# ls
fstab
# デフォルトオプションで圧縮する
[root@rocky86 0726]# compress fstab
[root@rocky86 0726]# ls
fstab.Z
# 解凍する
[root@rocky86 0726]# uncompress fstab.Z
[root@rocky86 0726]# ls
fstab
# 処理を表示する
[root@rocky86 0726]# compress -v fstab
fstab: -- replaced with fstab.Z Compression: 33.88%
# 解凍する
[root@rocky86 0726]# compress -dv fstab.Z
fstab.Z: -- replaced with fstab
# 元のファイルを保持する
[root@rocky86 0726]# compress -c fstab > fstab.Z
[root@rocky86 0726]# ls
fstab fstab.Z
```

例：ディレクトリを再帰的に圧縮する

```shell
[root@rocky86 0726]# tree dir1/
dir1/
├── dir2
│   └── messages
├── dnf.log
├── fstab
└── passwd
1 directory, 4 files
[root@rocky86 0726]# compress -vr dir1/
dir1//dir2/messages: -- replaced with dir1//dir2/messages.Z Compression: 71.74%
dir1//fstab: -- replaced with dir1//fstab.Z Compression: 33.88%
dir1//dnf.log: -- replaced with dir1//dnf.log.Z Compression: 80.21%
dir1//passwd: -- replaced with dir1//passwd.Z Compression: 45.24%
[root@rocky86 0726]# tree dir1/
dir1/
├── dir2
│   └── messages.Z
├── dnf.log.Z
├── fstab.Z
└── passwd.Z
1 directory, 4 files
# ディレクトリを再帰的に解凍する
[root@rocky86 0726]# compress -drv dir1/
dir1//dir2/messages.Z: -- replaced with dir1//dir2/messages
dir1//fstab.Z: -- replaced with dir1//fstab
dir1//dnf.log.Z: -- replaced with dir1//dnf.log
dir1//passwd.Z: -- replaced with dir1//passwd
```



## 1.2 gzipとgunzip

`gzip` パッケージから来ており、対応するファイルは `.gz` 拡張子を持ちます。
フォーマット：
```
gzip [OPTION]... FILE ...
gunzip [OPTION]... FILE ...
```

### よく使うオプション
- `-c | --stdout` : 圧縮データを標準出力に出力し、元のファイルを保持する
- `-d | --decompress` : 解凍、`gunzip`と同じ
- `-f | --force` : 既存の対象ファイルを上書きする
- `-k | --keep` : 元のファイルを保持する
- `-l | --list` : 元のファイルサイズ、圧縮ファイルサイズ、圧縮比、圧縮前のファイル名を表示する
- `-q | --quiet` : 静かなモード、警告を無視する
- `-r | --recursive` : ディレクトリ内のすべてのファイルを再帰的に圧縮する
- `-S | --suffix=SUF` : 圧縮ファイルの拡張子を指定する
- `-t | --test` : テスト、圧縮ファイルが完全かどうかを検出する
- `-v | --verbose` : 処理を表示する
- `-1 | --fast` : 最速の圧縮、圧縮率は最低だが、圧縮速度が速い
- `-9 | --best` : 最高の圧縮、圧縮率が最も高く、圧縮速度が遅い
- `-N` : 圧縮レベルを指定、値は1から9の間、デフォルトは6

例：

```shell
# 元のファイルを保持し、圧縮過程を表示する
[root@rocky86 0726]# gzip -vk fstab passwd
fstab: 50.3% -- created fstab.gz
passwd: 61.2% -- created passwd.gz
[root@rocky86 0726]# ls
dir1 fstab fstab.gz passwd passwd.gz shadow
# ファイルにリダイレクトする
[root@rocky86 0726]# gzip fstab -c > fstab.gz
# パイプ
[root@rocky86 0726]# cat passwd | gzip > pwd.gz
# カスタマイズした拡張子
[root@rocky86 0726]# gzip -kv fstab -S .gzzz
fstab: 50.3% -- created fstab.gzzz
# ディレクトリを再帰的に圧縮する
[root@rocky86 0726]# gzip -vrk dir1/
dir1/dir2/messages: 86.1% -- created dir1/dir2/messages.gz
dir1/fstab: 50.3% -- created dir1/fstab.gz
dir1/dnf.log: 91.2% -- created dir1/dnf.log.gz
dir1/passwd: 61.2% -- created dir1/passwd.gz
# 圧縮ファイル情報を表示する
[root@rocky86 0726]# gzip -l fstab.gz
compressed uncompressed ratio uncompressed_name
382 720 50.3% fstab
[root@rocky86 0726]# gzip -l fstab.gz passwd.gz
compressed uncompressed ratio uncompressed_name
382 720 50.3% fstab
1134 2858 61.2% passwd
1516 3578 58.3% (totals)

# 解凍
[root@rocky86 0726]# gunzip -vkf fstab.gz passwd.gz
fstab.gz: 50.3% -- replaced with fstab
passwd.gz: 61.2% -- replaced with passwd
```



## 1.3 bzip2とbunzip2

`bzip2` パッケージに由来し、対応するファイルは `.bz2` 拡張子を持ちます。
フォーマット：
```shell
bzip2 [OPTION]... FILE ...
bunzip2 [OPTION]... FILE ...
```

### よく使うオプション
- `-d | --decompress` : 解凍、`bunzip2` と同じ
- `-z | --compress` : 強制圧縮
- `-k | --keep` : 元のファイルを保持する
- `-f | --force` : 既存の対象ファイルを上書きする
- `-t | --test` : テスト、圧縮ファイルが完全かどうかを検出する
- `-c | --stdout` : 圧縮データを標準出力に出力し、元のファイルを保持する
- `-q | --quiet` : 静かなモード、警告を無視する
- `-v | --verbose` : 処理を表示する
- `-N` : 圧縮レベルを指定、値は1から9の間、デフォルトは9
- `--fast` : `-1`と同じ
- `--best` : `-9`と同じ

例：
```shell
# 元のファイルを保持し、過程を表示する
[root@rocky86 0726]# bzip2 -kv fstab passwd
fstab: 1.731:1, 4.622 bits/byte, 42.22% saved, 720 in, 416 out.
passwd: 2.516:1, 3.180 bits/byte, 60.25% saved, 2858 in, 1136 out.
# 出力をリダイレクトする
[root@rocky86 0726]# bzip2 fstab -cv > fstab.bz2
fstab: 1.731:1, 4.622 bits/byte, 42.22% saved, 720 in, 416 out.
# パイプと出力リダイレクト
[root@rocky86 0726]# cat fstab | bzip2 -cv > fstab.bz2
(stdin): 1.731:1, 4.622 bits/byte, 42.22% saved, 720 in, 416 out.
# 解凍
[root@rocky86 0726]# bunzip2 -kfv fstab.bz2
fstab.bz2: done
# 解凍せずにファイル内容を表示
[root@rocky86 0726]# bzcat fstab.bz2
```



## 1.4 xzとunxz

`xz` パッケージに由来し、対応するファイルは `.xz` 拡張子を持ちます。
フォーマット：
```shell
xz [OPTION]... FILE ...
unxz [OPTION]... FILE ...
```

### よく使うオプション
- `-z | --compress` : 強制圧縮
- `-d | --decompress` : 解凍、`unxz` と同じ
- `-t | --test` : テスト、圧縮ファイルが完全かどうかを検出する
- `-l | --list` : 圧縮ファイルの情報を表示する
- `-k | --keep` : 元のファイルを保持する
- `-f | --force` : 既存の対象ファイルを上書きする
- `-c | --stdout` : 圧縮データを標準出力に出力し、元のファイルを保持する
- `-T | --threads=NUM` : スレッド数を設定、デフォルトは1
- `-q | --quiet` : 静かなモード、警告を無視する
- `-v | --verbose` : 処理を表示する
- `-N` : 圧縮レベルを指定、値は1から9の間、デフォルトは6

例：
```shell
# 元のファイルを保持する
[root@rocky86 0726]# xz -kv messages
messages (1/1)
100 % 29.5 KiB / 393.1 KiB = 0.075
# 情報を表示
[root@rocky86 0726]# xz -l messages.xz
Strms Blocks Compressed Uncompressed Ratio Check Filename
1 1 29.5 KiB 393.1 KiB 0.075 CRC64 messages.xz
# リダイレクト
[root@rocky86 0726]# xz -kcv messages > msg.xz
messages (1/1)
100 % 29.5 KiB / 393.1 KiB = 0.075
# 解凍
[root@rocky86 0726]# unxz -vfk fstab.xz msg.xz
fstab.xz (1/2)
100 % 444 B / 720 B = 0.617
msg.xz (2/2)
100 % 29.5 KiB / 393.1 KiB = 0.075
```



## 1.5 zipとunzip

`zip` はディレクトリや複数のファイルを1つのファイルにまとめて圧縮することができますが、所有者やグループ情報などのファイル属性情報が失われる可能性があります。これらはそれぞれ `zip` と `unzip` パッケージに由来します。対応するファイルは `.zip` 拡張子を持ちます。

フォーマット：
```shell
zip [OPTION]... zipfile [FILE]...
unzip [OPTION]... zipfile [FILE]...
```

### zipのよく使うオプション
- `-f` : 新しいファイルを圧縮ファイルに交換する
- `-u` : 圧縮ファイルに既存なら更新、なければ追加
- `-d` : 圧縮ファイルから指定されたファイルを削除
- `-m` : ファイルを圧縮後、元のファイルを削除する
- `-r` : ディレクトリを再帰的に圧縮する
- `-j` : ファイル名および内容のみを保存し、ディレクトリ名は保存しない
- `-l` : 圧縮時にLFをLF+CRに変換、`unzip -l` は圧縮ファイルの内容を表示
- `-1` : 最速圧縮、数字1
- `-9` : 最高圧縮比、数字9
- `-q` : 静かなモード
- `-v` : 処理を表示する
- `-c` : 各圧縮ファイルにコメントを追加
- `-z` : 圧縮ファイルにコメントを追加、`unzip -z` でコメントを見る
- `-x` : 指定されたファイルを圧縮から除外
- `-i` : 指定されたファイルのみを圧縮
- `-D` : 圧縮ファイル内にディレクトリ名を作成しない
- `-T` : テスト、圧縮ファイルが完全かどうかを検出する
- `-X` : 余分なファイル属性を保存しない
- `-y` : シンボリックリンクをそのまま保存し、リンク先のファイルではない
- `-n` : 特定の文字列で終わるファイルを圧縮しない
- `-P` : パスワードを追加

### unzipのよく使うオプション
- `-p` : 圧縮内容をパイプで出力
- `-l` : 圧縮ファイル内のファイルを表示
- `-t` : テスト、圧縮ファイルが完全かどうかを検出する
- `-z` : コメントを見る
- `-v` : パッケージ内ファイル情報を一覧表示
- `-x` : 解凍から指定されたファイルを除外
- `-d` : 解凍後のターゲットディレクトリを指定
- `-n` : 解凍時に元のファイルを上書きしない
- `-q` : 静かなモード
- `-o` : 直接上書き
- `-a` : テキストファイルに必要な文字変換を行う
- `-j` : 圧縮ファイルに元々あるディレクトリパスを無視する
- `-C` : 圧縮ファイル内のファイル名を大文字小文字区別する
- `-L` : 圧縮ファイル内の全ファイル名を小文字に変換
- `-X` : 解凍時に元のUID/GIDを復元
- `-V` : VMSのファイルバージョン情報を保持
- `-K` : 解凍後に権限を復元
- `-M` : 出力結果を `more` プログラムに送る

例：
```shell
# ファイルmsg.zipを作成し、過程を表示
[root@rocky86 0726]# zip -v msg.zip messages
adding: messages (in=402508) (out=56530) (deflated 86%)
total bytes=402508, compressed=56530 -> 86% savings
# 内容を表示
[root@rocky86 0726]# unzip -l msg.zip
Archive: msg.zip
Length Date Time Name
--------- ---------- ----- ----
402508 07-26-2022 09:03 messages
--------- -------
402508 1 file
# パイプで新しいファイルを圧縮ファイルに追加
[root@rocky86 0726]# cat passwd | zip msg.zip passwd
# 内容を表示
[root@rocky86 0726]# unzip -l msg.zip
Archive: msg.zip
Length Date Time Name
--------- ---------- ----- ----
402508 07-26-2022 09:03 messages
2858 07-25-2022 22:09 passwd
--------- -------
405366 2 files
# txtファイルのみを圧縮
[root@rocky86 0726]# zip -i"*txt" txt.zip *
adding: f1.txt (deflated 86%)
adding: f2.txt (deflated 86%)
adding: f3.txt (deflated 86%)
# txtファイルのみを圧縮
[root@rocky86 0726]# zip txt2.zip ./*txt
adding: f1.txt (stored 0%)
adding: f2.txt (deflated 86%)
adding: f3.txt (deflated 86%)
```

### 例：再帰圧縮

```shell
# ディレクトリ構造を作成
[root@rocky86 0726]# tree dir1/
dir1/
├── dir2
│   └── messages
├── dnf.log
├── fstab
└── passwd
1 directory, 4 files

# 再帰的にディレクトリを圧縮
[root@rocky86 0726]# zip -r test1.zip dir1/
adding: dir1/ (stored 0%)
adding: dir1/dir2/ (stored 0%)
adding: dir1/dir2/messages (deflated 86%)
adding: dir1/fstab (deflated 50%)
adding: dir1/passwd (deflated 61%)
adding: dir1/dnf.log (deflated 91%)

# カレントディレクトリ内のすべてのファイルを圧縮
[root@rocky86 0726]# cd dir1/
[root@rocky86 dir1]# zip ../test2.zip *
adding: dir2/ (stored 0%)
adding: dnf.log (deflated 91%)
adding: fstab (deflated 50%)
adding: passwd (deflated 61%)
[root@rocky86 dir1]# cd ..
[root@rocky86 0726]# ll test*
-rw-r--r-- 1 root root 76768 Jul 26 15:02 test1.zip
-rw-r--r-- 1 root root 46255 Jul 26 15:02 test2.zip
```

#### 例：圧縮ファイルの内容を表示
```shell
# 内容を表示
[root@rocky86 0726]# unzip -l test1.zip
Archive: test1.zip
Length Date Time Name
--------- ---------- ----- ----
0 07-26-2022 15:01 dir1/
0 07-25-2022 22:30 dir1/dir2/
216607 07-25-2022 21:41 dir1/dir2/messages
720 07-25-2022 21:39 dir1/fstab
2858 07-25-2022 21:43 dir1/passwd
501645 07-25-2022 21:40 dir1/dnf.log
--------- -------
721830 6 files

[root@rocky86 0726]# unzip -l test2.zip
Archive: test2.zip
Length Date Time Name
--------- ---------- ----- ----
0 07-25-2022 22:30 dir2/
501645 07-25-2022 21:40 dnf.log
720 07-25-2022 21:39 fstab
2858 07-25-2022 21:43 passwd
--------- -------
505223 4 files
```

### 例：パスワードを設定

#### 非対話型での暗号化・解凍

```shell
[root@rocky86 dir1]# zip -vP 123456 test.zip dnf.log
adding: dnf.log (in=501645) (out=44208) (deflated 91%)
total bytes=501645, compressed=44220 -> 91% savings

[root@rocky86 dir1]# unzip -P 123456 test.zip
Archive: test.zip
inflating: dnf.log
```

#### 対話型での暗号化・解凍

```shell
[root@rocky86 dir1]# zip -ve test.zip dnf.log
Enter password:
Verify password:
updating: dnf.log (in=501645) (out=44208) (deflated 91%)
total bytes=501645, compressed=44220 -> 91% savings

[root@rocky86 dir1]# unzip test.zip
Archive: test.zip
[test.zip] dnf.log password:
inflating: dnf.log
```
### 例: 更新と削除

```shell
# 圧縮ファイルの内容を表示
[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length      Date    Time    Name
---------  ---------- ----- ----
2226376    07-26-2022 14:12 f1.txt
1946847    07-26-2022 14:09 f2.txt
1814952    07-26-2022 14:09 f3.txt
---------                  -------
5988175                   3 files

[root@rocky86 0726]# echo "123">f1.txt
[root@rocky86 0726]# ll f1.txt passwd
-rw------- 1 root root    4 Jul 26 14:19 f1.txt
-rw-r--r-- 1 root root 2858 Jul 25 22:09 passwd

# 圧縮ファイル内に存在しない場合、追加する
[root@rocky86 0726]# zip -vu txt.zip f1.txt passwd
updating: f1.txt (in=4) (out=4) (stored 0%)
adding: passwd (in=2858) (out=1109) (deflated 61%)
total bytes=3764661, compressed=525257 -> 86% savings

# 再度内容を確認し、f1.txt が更新された
[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length      Date    Time    Name
---------  ---------- ----- ----
4          07-26-2022 14:19 f1.txt
1946847    07-26-2022 14:09 f2.txt
1814952    07-26-2022 14:09 f3.txt
2858       07-25-2022 22:09 passwd
---------                  -------
3764661                   4 files

# 追加せずに更新のみ
[root@rocky86 0726]# zip -vf txt.zip f1.txt messages
freshening: f1.txt (in=7) (out=7) (stored 0%)
total bytes=3764664, compressed=525260 -> 86% savings

# messagesは圧縮ファイルに追加されなかった
[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length      Date    Time    Name
---------  ---------- ----- ----
7          07-26-2022 14:24 f1.txt
1946847    07-26-2022 14:09 f2.txt
1814952    07-26-2022 14:09 f3.txt
2858       07-25-2022 22:09 passwd
---------                  -------
3764664                   4 files

# txt.zipからf3.txtを削除
[root@rocky86 0726]# zip -d txt.zip f3.txt
deleting: f3.txt

[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length      Date    Time    Name
---------  ---------- ----- ----
7          07-26-2022 14:24 f1.txt
1946847    07-26-2022 14:09 f2.txt
2858       07-25-2022 22:09 passwd
---------                  -------
1949712                   3 files
```

### 例: コメント

```shell
# コメントを追加、Ctrl+Dで終了
[root@rocky86 0726]# zip -z txt.zip
enter new zip file comment (end with .):
this is test des

# コメントを表示、unzip -lでも表示可能
[root@rocky86 0726]# unzip -z txt.zip
Archive: txt.zip
this is test des
```

### 例: 解凍

```shell
# 指定したディレクトリに解凍、一部のファイルは解凍しない
[root@rocky86 0726]# unzip txt.zip -x f3.txt -d ./txt
Archive: txt.zip
inflating: ./txt/f1.txt
inflating: ./txt/f2.txt

[root@rocky86 0726]# ll txt
total 1912
-rw-r--r-- 1 root root    4453 Jul 26 15:19 f1.txt
-rw------- 1 root root 1946847 Jul 26 14:09 f2.txt

# 内容を表示
[root@rocky86 0726]# unzip -v txt.zip
Archive: txt.zip
Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  -------- ---- ---------- ----- -------- ----
4453     Defl:N      1661  63%  07-26-2022 15:19 a30efa6e f1.txt
1946847  Defl:N    269213  86%  07-26-2022 14:09 add171e4 f2.txt
1814952  Defl:N    254931  86%  07-26-2022 14:09 eb2f160b f3.txt
--------          -------- ---                                -------
3766252           525805  86%   3 files
```


## 1.6 zcat

zcat は "zip cat" の略で、名前からわかるように圧縮ファイルの内容を解凍せずに表示するためのコマンドです。

### 使用例

```shell
zcat [OPTION]... [FILE]...
```

### よく使うオプション

- `-c` : 内容を標準出力に出力する（デフォルト）
- `-d` : 解凍する
- `-l` : 圧縮ファイル（パッケージ）のファイルリストを表示する
- `-r` : 目上の再帰操作
- `-t` : 圧縮ファイルの完全性をテストする

例えば：

```shell
[root@rocky86 0726]# zcat fstab.Z
[root@rocky86 0726]# zcat fstab.gz
[root@rocky86 0726]# zcat fstab.zip
```

## 1.7 圧縮率の比較

```shell
[root@rocky86 0725]# compress hwdb.bin -vc > hwdb.bin.Z
[root@rocky86 0725]# gzip -kv hwdb.bin
[root@rocky86 0725]# bzip2 -kv hwdb.bin
[root@rocky86 0725]# xz -kv hwdb.bin
[root@rocky86 0725]# zip -v hwdb.zip hwdb.bin
[root@rocky86 0725]# ll hwdb.* -h -S
-r--r--r-- 1 root root 11M Jul 26 20:48 hwdb.bin
-rw-r--r-- 1 root root 2.8M Jul 26 21:40 hwdb.bin.Z
-rw-r--r-- 1 root root 2.0M Jul 26 21:41 hwdb.zip
-r--r--r-- 1 root root 2.0M Jul 26 20:48 hwdb.bin.gz
-r--r--r-- 1 root root 1.7M Jul 26 20:48 hwdb.bin.bz2
-r--r--r-- 1 root root 1.4M Jul 26 20:48 hwdb.bin.xz
```
### 実行結果:

- `hwdb.bin`: 11M
- `hwdb.bin.Z`: 2.8M (compress)
- `hwdb.zip`: 2.0M (zip)
- `hwdb.bin.gz`: 2.0M (gzip)
- `hwdb.bin.bz2`: 1.7M (bzip2)
- `hwdb.bin.xz`: 1.4M (xz)

以上より、xzが最も高い圧縮率を持っていることがわかります。