Linux 圧縮 / アーカイブ

# はじめに

データのサイズを小さくする処理を **圧縮** と言う。単一のファイルに対して行われる。

複数のファイルやディレクトリを1つのファイルにまとめる処理を **アーカイブ** と言う。アーカイブされたファイルのデータサイズは、元のファイルと変わらない（アーカイブに圧縮処理は含まれない）。

「圧縮」と「アーカイブ」は別の概念だが、実際には **アーカイブされたファイルは圧縮される** ことも多く、一般的に「圧縮ファイル」と言うとアーカイブされたものを指すことがある。

`$ tar` コマンドでは `-z` オプションをつけることで、複数ファイルをアーカイブした上で、さらに圧縮までを同時に行うことができる。

:::note info
圧縮は、単一のファイルに対して行う処理
アーカイブは、複数ファイルを単一ファイルにまとめる処理
:::

圧縮されたファイルを復元することを **解凍**、アーカイブされたファイルを解体することを **展開** と表現する。

実際には `.tar.gz` など、圧縮とアーカイブが組み合わさった形式が多く、一般的には解凍（uncompress）と展開（extract）が同時に行われるケースが多い。

# 圧縮

一般的な圧縮コマンド（`$ gzip`、 `$ bzip2`、`$ xz`）は、1 回の処理で 1 つのファイルしか圧縮できない。

そのため、複数のファイルを圧縮したい場合は、まずアーカイブで 1 つのファイルにまとめる必要がある。

## 拡張子

- `$ gzip` ： `.gz`
- `$ bzip2` ： `.bg2`
- `$ xz` ： `.xz`


## 圧縮効率

```:圧縮効率
gzip < bxip2 < xz
```

## 処理速度

```:処理速度
gzip > bxip2 > xz
```

## 圧縮する

```console:ファイルを圧縮する
$ gzip ファイル
$ bzip2 ファイル
$ xz ファイル
```

```console:元ファイルを残しつつ圧縮する（keep）
$ gzip -k ファイル
$ bzip2 -k ファイル
$ xz -k ファイル
```

`-c` で圧縮ファイル（ストリーム）を [標準出力](https://qiita.com/AsahinaKei/items/301b88e464c23aba231e#%E6%A8%99%E6%BA%96%E5%87%BA%E5%8A%9B--stdout) として出力することができる。

[パイプ](https://qiita.com/AsahinaKei/items/301b88e464c23aba231e#%E3%83%91%E3%82%A4%E3%83%97--)（`|`） と [リダイレクト](https://qiita.com/AsahinaKei/items/301b88e464c23aba231e)（`>`）を組み合わせると、元ファイルを残しながら圧縮することができる。

```console:元ファイルを残しつつ圧縮する
$ gzip -c ファイル > 圧縮ファイル
$ bzip2 -c ファイル > 圧縮ファイル
$ xz -c ファイル名 > 圧縮ファイル
```

`-r` オプションは、再帰的に対象ディレクトリ内を圧縮するが、アーカイブした上で圧縮するわけではなく、それぞれのファイルに対して圧縮を個別に実施する。

```console:ディレクトリ内のファイルをそれぞれ圧縮する（アーカイブはしない）
$ gzip -r ディレクトリ
$ bzip2 -r ディレクトリ
$ xz -r ディレクトリ
```

## 解凍する

```console:圧縮ファイルを解凍する
$ gzip -d 圧縮ファイル
$ bzip2 -d 圧縮ファイル
$ xz -d 圧縮ファイル
```

```console:圧縮ファイルを解凍する
$ ungzip 圧縮ファイル
$ bunzip2 圧縮ファイル
$ unxz 圧縮ファイル
```

## 閲覧する

圧縮ファイル専用の `$ cat` コマンド。

```console:圧縮ファイルを閲覧する
$ zcat 圧縮ファイル
$ bzcat 圧縮ファイル
$ xzcat 圧縮ファイル
```

※ 圧縮されたアーカイブに対しては、使用不可

## 検索する

圧縮ファイル専用の `$ grep` コマンド。

```console:圧縮ファイル内の文字列を検索する
$ zgrep "検索文字列" 圧縮ファイル
$ bzgrep "検索文字列" 圧縮ファイル
$ xzgrep "検索文字列" 圧縮ファイル
```

# アーカイブ

複数のファイルを単一ファイルにまとめる処理。

以降の説明では `-v` （verbose）オプションをつけて例を示す。`-v` オプションをつけることで、処理中の状態を出力することができる。

## 拡張子

- アーカイブのみ
    - `.tar`
- アーカイブした上で、圧縮も実行した時
    - `.tar.gz`
    - `.tar.bx2`
    - `.tar.xz`
    - `.tgz`（`.tar.gz` の短縮形）

## アーカイブを作成する

```console:アーカイブを作成する（create）
$ tar -c ファイル1 ファイル2
```


```console:アーカイブを作成する（verbose）
$ tar -cv ファイル1 ファイル2
```

```console:ファイル名を指定してアーカイブを作成する（file）
$ tar -cvf アーカイブ ファイル1 ファイル2
$ tar -cvf アーカイブ ディレクトリ
$ tar -cvf アーカイブ ファイル1 ファイル2 ディレクトリ  # ディレクトリもアーカイブ可能
```

`$ tar` コマンドのオプションは GNU tar では `-` を省略可能だが、BSD tar（macOS など）では `-` が省略できない場合がある。  

ただし、オプション `f` に `-` をつけて `-f` とした場合に限っては、直後の文字が引数扱いになってしまうため、`f` をオプションの末尾にする必要がある。

:::note info
オプション `f` に `-` をつける場合、 `f` はオプションの末尾に記述する
```console:動作しない
$ tar -fc アーカイブファイル名 ファイル1 ファイル2
```

```console:動作する
$ tar -cvf アーカイブファイル名 ファイル1 ファイル2
$ tar fvc アーカイブファイル名 ファイル1 ファイル2 # ハイフンなしなら順番は関係ない
$ tar cvfアーカイブファイル名 ファイル1 ファイル2 # スペースを開けなくても動作する
```
:::

## アーカイブにファイルを追加する

```console:アーカイブにファイルを追加する（replace, record）
$ tar -rf アーカイブファイル 追加ファイル
```

※ 圧縮されたファイルには使用不可

## アーカイブの中を閲覧する

```console:アーカイブの内を閲覧する（table）
$ tar -tvf アーカイブファイル
```

## 圧縮されたアーカイブの中を閲覧する

```console:圧縮されたアーカイブの内を閲覧する
$ tar -tvzf 圧縮アーカイブファイル  # gzip(.tar.gz)
$ tar -tvjf 圧縮アーカイブファイル  # bzip2(.tar.bz2)
$ tar -tvJf 圧縮アーカイブファイル  # xz(.tar.xz)
```

## アーカイブを展開する
extract=抽出する

```console:アーカイブを展開する（extract）
$ tar -xvf アーカイブファイル
```

## アーカイブを作成した上で圧縮も行う

```console:圧縮したアーカイブを作成する
$ tar -zvf 圧縮アーカイブファイル名 ファイル1 ファイル2  # gzip
$ tar -jvf 圧縮アーカイブファイル名 ファイル1 ファイル2  # bzip2
$ tar -Jvf 圧縮アーカイブファイル名 ファイル1 ファイル2  # xz
```

## 圧縮されたアーカイブを解凍して展開する

```console:圧縮したアーカイブを解凍・展開する（extract）
$ tar -xvzf 圧縮アーカイブファイル  # gzip(.tar.gz)
$ tar -xvjf 圧縮アーカイブファイル  # bzip2(.tar.bz2)
$ tar -xvJf 圧縮アーカイブファイル  # xz(.tar.xz)
```

# `$ cpio`

`$ tar` と似ているが [標準入力・標準出力](https://qiita.com/AsahinaKei/items/301b88e464c23aba231e) を使ってデータを処理するのが特徴。

- `-o` オプション
- [パイプ](https://qiita.com/AsahinaKei/items/301b88e464c23aba231e#%E3%83%91%E3%82%A4%E3%83%97--)（`|`）
- [リダイレクト](https://qiita.com/AsahinaKei/items/301b88e464c23aba231e)（`>`）

を組み合わせるとアーカイブ（`.cpio`）を作成できる。

```console:標準入力からアーカイブを作成する（out）
$ find . -type f | cpio -o > アーカイブファイル
```

```console:アーカイブを展開する（input）
$ cpio -i < アーカイブファイル
$ cpio -id < アーカイブファイル # アーカイブ内のサブディレクトリを展開時に自動で生成する
```

```console:アーカイブの内容を閲覧する（table）
$ cpio -t < アーカイブファイル
```

```console:ファイルをディレクトリ構造ごと別の場所へコピーする（pass-through)
$ find . -type f | cpio -p ディレクトリ  # ディレクトリの存在が前提
$ find . -type f | cpio -pd ディレクトリ # 必要に応じてディレクトリを作成（推奨）
```


# 圧縮形式を調べる

```console:ファイルの種類を判別する
$ file ファイル
```