🦔

go installしたものを一括で更新する方法

2022/02/19に公開

結論

zsh ですが、簡単なスクリプトで実現できそうです。

pushd ~
local gobin="$(go env GOBIN)"
local gobin="${gobin:-$(go env GOPATH)/bin}"
print -rl ${gobin}/*(*) | while read file; do
    local pkg="$(go version -m "${file}" | head -n2 | tail -n1 | awk '{print $2}')"
    go install "${pkg}@latest"
done
popd

解説

実行ファイルから出自を知る

忘れがちですが、 go version -m は、ビルドした実行ファイルを取れるんですね。

多謝、 @skanehira !

https://knqyf263.hatenablog.com/entry/2021/02/12/162928

$ go version -m ~/go/bin/goimports
/home/kyoh86/go/bin/goimports: go1.17.7
        path    golang.org/x/tools/cmd/goimports
        mod     golang.org/x/tools      v0.1.9  h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
        dep     golang.org/x/mod        v0.5.1  h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
        dep     golang.org/x/sys        v0.0.0-20211019181941-9d821ace8654      h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
        dep     golang.org/x/xerrors    v0.0.0-20200804184101-5ec99f83aff1      h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=

zshをちょっと頑張る

まずはglobalなgo installでインストールされる先を特定します。

local gobin="$(go env GOBIN)"
local gobin="${gobin:-$(go env GOPATH)/bin}"

GOBINを設定している場合はその場所を指すべきだし、指定されていないならGOPATH/binでしょう。

次に特定ディレクトリ(今回はgo/bin)配下の実行ファイルをリストアップします。
これには、zshのextended globが大変便利ですね。
まともにやるなら find とか使うんでしょうが…

print -rl ${gobin}/*(*) | while read file; do
    # ...
done

あとはgo version -mの出力から2行目2列目だけ引っ張り出せば、Package Pathが抽出できます。
(より厳密には、1列目==pathをちゃんと抽出するべきですが、面倒なので簡略化しています)

go version -m "${file}" | head -n2 | tail -n1 | awk '{print $2}'

これを変数pkgに放り込んで、 go install に渡してやれば良い。

go install "${pkg}@latest"

direnvとか、go.modとかに影響されると面倒くさいので、前後にhomedirへの移動と復帰をはさみます。

pushd ~
# ...
popd

ということで全体構造を再掲します。

pushd ~
local gobin="$(go env GOBIN)"
local gobin="${gobin:-$(go env GOPATH)/bin}"
print -rl ${gobin}/*(*) | while read file; do
    local pkg="$(go version -m "${file}" | head -n2 | tail -n1 | awk '{print $2}')"
    go install "${pkg}@latest"
done
popd

終わりに

この記事はQiitaの拙著記事 $GOPATH/binにいるバイナリ群の出自を探る方法 を元に、大幅に書き直したものです。
goはmodule awareのサポート前後で大きく環境が異なるので、情報を選ぶ時は投稿日などには十分注意したいですね。

Discussion