Skip to content

Instantly share code, notes, and snippets.

@holly
Created March 27, 2026 03:21
Show Gist options
  • Select an option

  • Save holly/933f4e9594fc3ee67a8cb8eadfb3077e to your computer and use it in GitHub Desktop.

Select an option

Save holly/933f4e9594fc3ee67a8cb8eadfb3077e to your computer and use it in GitHub Desktop.
shfmt install
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
set -C
# 設定
REPO="mvdan/sh"
API_URL="https://api.github.com/repos/${REPO}/releases/latest"
INSTALL_DIR="$HOME/.local/bin"
BINARY_NAME="shfmt"
CURL_OPTS=(-sSfL)
if [ -n "$GITHUB_TOKEN" ]; then
echo "Using GITHUB_TOKEN for authentication."
CURL_OPTS+=(-H "Authorization: token ${GITHUB_TOKEN}")
fi
# 依存コマンドのチェック
if ! command -v curl &>/dev/null; then
echo "Error: curl is required but not installed." >&2
exit 1
fi
if ! command -v jq &>/dev/null; then
echo "Error: jq is required but not installed." >&2
exit 1
fi
# 1. APIから最新リリース情報を取得し、tag_nameを取得
echo "Fetching latest release information..."
JSON_RESPONSE=$(curl "${CURL_OPTS[@]}" "$API_URL")
TAG_NAME=$(echo "$JSON_RESPONSE" | jq -r .tag_name)
if [ -z "$TAG_NAME" ] || [ "$TAG_NAME" = "null" ]; then
echo "Error: Could not fetch tag_name from API." >&2
exit 1
fi
echo "Latest version: $TAG_NAME"
# 3. すでにshfmtがインストールされていて、同じバージョンであれば終了
if command -v "$BINARY_NAME" &>/dev/null; then
CURRENT_VERSION=$("$BINARY_NAME" --version 2>/dev/null)
if [ "$CURRENT_VERSION" = "$TAG_NAME" ]; then
echo "shfmt $TAG_NAME is already installed. Skipping."
exit 0
fi
fi
# 4. uname -s, uname -mの結果に合わせて適切なassetsのURLを取得
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
# アーキテクチャのマッピング (shfmtの命名規則に合わせる)
case "$ARCH" in
x86_64) ARCH="amd64" ;;
aarch64) ARCH="arm64" ;; # Linux aarch64
arm64) ARCH="arm64" ;; # macOS arm64
i386 | i686) ARCH="386" ;;
esac
# 例: shfmt_v3.13.0_darwin_amd64 のようなパターンを検索
# APIレスポンス内で name に "_${OS}_${ARCH}" を含むものを探す
DOWNLOAD_URL=$(echo "$JSON_RESPONSE" | jq -r --arg os "$OS" --arg arch "$ARCH" \
'.assets[] | select(.name | test("_\($os)_\($arch)$")) | .browser_download_url' | head -n 1)
if [ -z "$DOWNLOAD_URL" ]; then
echo "Error: No matching download URL found for OS=$OS, ARCH=$ARCH." >&2
exit 1
fi
echo "Download URL: $DOWNLOAD_URL"
# 5. ~/.local/bin にインストール
mkdir -p "$INSTALL_DIR"
# バイナリをダウンロード(バージョン付きで保存)
BINARY_PATH="${INSTALL_DIR}/${BINARY_NAME}-${TAG_NAME}"
echo "Downloading to $BINARY_PATH..."
curl -sL "$DOWNLOAD_URL" -o "$BINARY_PATH"
chmod +x "$BINARY_PATH"
# 6. shfmtという名前にsymlinkを作成する
SYMLINK_PATH="${INSTALL_DIR}/${BINARY_NAME}"
# 既存のシンボリックリンクやファイルがあれば削除
if [ -L "$SYMLINK_PATH" ]; then
rm "$SYMLINK_PATH"
elif [ -e "$SYMLINK_PATH" ]; then
echo "Warning: Removing existing file at $SYMLINK_PATH"
rm "$SYMLINK_PATH"
fi
ln -s "$BINARY_PATH" "$SYMLINK_PATH"
echo ""
echo "Installation complete!"
echo "Version: $TAG_NAME"
echo "Binary: $BINARY_PATH"
echo "Link: $SYMLINK_PATH"
# パスが通っていない場合の警告
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
echo ""
echo "Warning: $INSTALL_DIR is not in your PATH."
echo "Please add the following line to your .bashrc or .zshrc:"
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment