こんにちは、山田ハヤオです。最近Gentoo Linuxの勉強に勤しんでいます。
Arch Linuxのpacmanは完璧なツールで、パッケージのインストールや削除、更新はもちろん、様々な形式でパッケージの一覧を表示したり設定を表示したりできます。
対して、Gentoo LinuxのPortageはパッケージの一覧を手軽に表示するツールは標準では備わっていません。(自分が知っている限り)
通常の場合はeixやequeryといった外部ツールを使うらしいですが、追加でインストールする必要がある以上シェルスクリプトで利用するには抵抗があります。
今回はそういった外部ツールを使わずに、シェルで扱いやすい形式でパッケージ一覧を取得します。
gentooリポジトリの全てのパッケージを取得
find /var/db/repos/gentoo/ -mindepth 3 -maxdepth 3 -type f -name '*.ebuild' | sed -e 's|/var/db/repos/gentoo/||g' -e 's|.ebuild$||g' | awk -F "/" '{print $1"/"$3}'
自分の環境の設定では、gentooリポジトリのデータは/var/db/repos/gentoo
に入っていたので、そこからデータを取得しています。
実際にスクリプトで利用する際にはこのパスは変更可能なので、以下のコマンドで取得できるINIファイルをパースする必要があります。
cat /etc/portage/repos.conf /etc/portage/repos.conf/* 2> /dev/null
INIファイルの解析から丁寧に実装してあげるとこんな感じ。解析はちょっと雑だけど許して…
#!/usr/bin/env bash
CurrentSection="" MainRepo="" MainRepoPath=""
set -euo pipefail
while read -r line; do
case "$(sed -e 's/^ *//' -e 's/ *$//' <<< "$line")" in
"["*"]")
CurrentSection="$line"
continue
;;
"main-repo"*"="*)
[[ "$CurrentSection" = "[DEFAULT]" ]] || continue
#shellcheck disable=SC2001
MainRepo="$(sed -e "s|^main-repo *= *||g" <<< "$line")"
;;
"location"*"="*)
[[ -n "${MainRepo-""}" ]] || continue
[[ "$CurrentSection" = "[$MainRepo]" ]] || continue
#shellcheck disable=SC2001
MainRepoPath="$(sed -e "s|^location *= *||g" <<< "$line")"
;;
*)
continue
;;
esac
done < <(cat /etc/portage/repos.conf /etc/portage/repos.conf/* 2> /dev/null)
MainRepoPath="$(realpath "$MainRepoPath")"
find "$MainRepoPath" -mindepth 3 -maxdepth 3 -type f -name '*.ebuild' | sed -e "s|${MainRepoPath%/}/||g" -e 's|.ebuild$||g' | awk -F "/" '{print $1"/"$3}'
指定したリポジトリのパッケージを全て取得
上記のコードをちょっと流用するだけでどのリポジトリでも簡単に一覧を取得できます。
eselect repositoryだろうがlaymanだろうがなんだって使えます。
#!/usr/bin/env bash
# 一覧を表示したいリポジトリ名
TargetRepo="gentoo-zh"
CurrentSection="" RepoPath=""
set -euo pipefail
while read -r line; do
case "$(sed -e 's/^ *//' -e 's/ *$//' <<< "$line")" in
"["*"]")
CurrentSection="$line"
continue
;;
"location"*"="*)
[[ "$CurrentSection" = "[$TargetRepo]" ]] || continue
#shellcheck disable=SC2001
RepoPath="$(sed -e "s|^location *= *||g" <<< "$line")"
;;
*)
continue
;;
esac
done < <(cat /etc/portage/repos.conf /etc/portage/repos.conf/* 2> /dev/null)
RepoPath="$(realpath "$RepoPath")"
find "$RepoPath" -mindepth 3 -maxdepth 3 -type f -name '*.ebuild' | sed -e "s|${RepoPath%/}/||g" -e 's|.ebuild$||g' | awk -F "/" '{print $1"/"$3}'
全てのリポジトリの全てのパッケージを取得
リポジトリを指定しないなら雑にINIを解析すればいいだけなので、こんな感じのワンライナーで一覧表示できます。xargsは神
cat /etc/portage/repos.conf /etc/portage/repos.conf/* 2> /dev/null | sed -e 's/^ *//' -e 's/ *$//' | grep "^ *location *=" | sed -e 's/^location *= *//' | xargs -L1 realpath | xargs -I{} bash -c "find '{}' -mindepth 3 -maxdepth 3 -type f -name '*.ebuild' | sed -e 's|{}/||g' -e 's|.ebuild$||g'" | awk -F "/" '{print $1"/"$3}'
インストールされている全てのパッケージを取得
find /var/db/pkg/ -mindepth 2 -maxdepth 2 -type d | sed 's|/var/db/pkg/||g'
たぶんこっちは/var/db/pkg
で固定なので、パス名をそのままハードコードして良いと思います。
@worldのパッケージを全て取得
@worldは明示的にインストールしたパッケージのことです。
/var/db/portage/world
にその一覧はあるのですが、余分な情報があったりバージョンが欠けていたりするので形式を統一して扱いやすくします。
sed -E 's|:.+$||g' /var/lib/portage/world | xargs -I{} bash -c 'ls -d /var/db/pkg/{}-* | sed "s|/var/db/pkg/||g" | grep -E "{}-[0-9]"'
バージョン番号を消す
上のコマンドはすべて<カテゴリ>/<パッケージ名>-<バージョン>
という形式で出力されます。
ただ、バージョン番号はいらないという状況も多いと思います。なのでバージョン番号を削除するワンライナーです。
sed -E 's|\-[0-9]+.+||g'
単純な正規表現です。実際に使うとこんな感じ。
echo "x11-misc/qt5ct-1.5" | sed -E 's|\-[0-9]+.+||g'
# 出力は x11-misc/qt5ct
終わり
まだGentooを触って日が浅いのでそこまで多くのネタが無いです。
またいい感じにワンライナーが溜まってきたらまとめようと思います。
それでは、また今度。
コメント