Elixir erl_tar で tar.gz ファイルを解凍


[:erl_tar.extract/2]: https://www.erlang.org/doc/man/erl_tar.html#extract-2
[livebook desktop]: https://news.livebook.dev/introducing-the-livebook-desktop-app-4C8dpu
[iex]: https://elixirschool.com/ja/lessons/basics/iex_helpers
[req]: https://hexdocs.pm/req/readme.html
[Nerves]: https://hexdocs.pm/nerves/getting-started.html
[Elixir]: https://elixir-lang.org/
[tar]: https://en.wikipedia.org/wiki/Tar_(computing)

## はじめに

Elixir で[`tar.gz`][tar]ファイルを解凍するには[:erl_tar.extract/2]が便利なようです。
ちょっと癖があるので軽くまとめます。

論より Run。実際にイゴかしてみます。[^いごく]

https://qiita.com/torifukukaiou/items/17d55cf896c24b13350e


## [IEx](もしくは[Livebook Desktop])を開く

[Elixir]言語をRunできる環境を準備します。
[IEx]に使い慣れてる方はいつも通りに開きます。
初めての方には[Livebook Desktop]が便利です。

```elixir
iex
```

https://elixirschool.com/ja/lessons/basics/iex_helpers

https://news.livebook.dev/introducing-the-livebook-desktop-app-4C8dpu

## HTTP クライアント[req]をインストール

複数ある[Elixir]のHTTPクライアントの中で比較的使いやすい[req]を使用します。

```elixir
Mix.install([:req])
```

https://hexdocs.pm/req/readme.html

https://qiita.com/torifukukaiou/items/4d842c6acae2b8967467

## 試しに[Nerves]の`.tar.gz`ファイルをダウンロード

```elixir
tarball_url = "https://github.com/nerves-project/nerves_system_rpi0/releases/download/v1.20.0/nerves_system_rpi0-portable-1.20.0-F0DA416.tar.gz"
%{status: 200, body: compressed_data} = Req.get!(tarball_url)
compressed_data
```

https://hexdocs.pm/nerves/getting-started.html

https://nerves-jp.connpass.com/

https://www.erlang.org/doc/man/erl_tar.html#extract-2

https://en.wikipedia.org/wiki/Tar_(computing)


## 解凍する

解凍方法は大きく分けて2通りあります。
### `:cwd`

解凍結果をローカルのファイルシステムに保存するやり方です。

```elixir
# 保存先のディレクトリ
tmp_dir = "tmp"

# 解凍結果の場所
root_dir = (
  [
    tmp_dir,
    Path.split(tarball_url)
    |> Enum.reverse()
    |> hd()
    |> String.trim_trailing(".tar.gz")
  ]
  |> Path.join()
)

# 解凍する
:erl_tar.extract({:binary, compressed_data}, [:compressed, {:cwd, tmp_dir}])

# 解凍結果を検証
files1 = File.ls!(root_dir)
```

### `:memory`

メモリー上で展開するパターンです。

```elixir
# 解凍する
files2 =
  with {:ok, decompressed} <-
          :erl_tar.extract({:binary, compressed_data}, [:compressed, :memory]) do
    decompressed
    # ファイル名がcharlistなのでElixirで扱いやすいStringにする。
    |> Enum.map(fn {file, content} -> {to_string(file), content} end)
    # ファイル名で簡単にアクセスできるようMapにする。
    |> Map.new()
  end

# 解凍結果を検証
files2 |> Map.keys()
files2["nerves_system_rpi0-portable-1.20.0-F0DA416/.config"]
```

## おわりに

[:erl_tar.extract/2]のご紹介をしました。
特別難しくはないですが暗記しづらい処理なのでこういったハンズオンの記事があると便利なんじゃないかな〜と思いまとめてみました。
自分用のメモですが、参考になれば幸いです。

Elixirを楽しみましょう！

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf#_reference-cd6d9a3b524df507752a

# <u><b>Elixirコミュニティに初めて接する方は下記がオススメです</b></u>

**Elixirコミュニティ の歩き方 －国内オンライン編－**<br>
https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/f891b7ad-d2c4-3303-915b-f831069e28a4.png)](https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian)

**日本には28箇所のElixirコミュニティがあります**<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/7fdc5db7-dfad-9d10-28f8-1e0b8830a587.png)

## 日程からイベントを探すならElixirイベントカレンダー:calendar:

https://elixir-jp-calendar.fly.dev

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/985acaa4-50c9-da42-ae32-50fbf9119e61.png)](https://elixir-jp-calendar.fly.dev/)


[^いごく]: https://qiita.com/torifukukaiou/items/173a6d86d7a15649c5b5#fn-2