fish (shell) 解説書
「設定不要で最初から使いやすい」を掲げる現代的なコマンドラインシェル fish(Friendly Interactive Shell)の基本設計、強力な対話機能、独自文法、プラグイン運用から高度なカスタマイズまでを体系的に解説する手引きです。
章構成
-
1. 入門編:Fishの概要と特徴・環境構築
fish の設計哲学、従来のシェル(Bash/Zsh)との違い、オートサジェストやシンタックスハイライトなどの標準機能、および各 OS での環境構築を解説します。
-
2. 入門編:インタラクティブ操作と基本機能
マニュアル参照に基づく高精度なタブ補完、コマンド履歴検索、Web ブラウザを使った設定 UI(
fish_config)、およびキーバインド操作を解説します。 -
3. 入門編:Fish文法の基本とBashとの違い
Bash との意図的な非互換性とクリーンな構文、クォート文字列の展開規則、コマンド置換(
(...))、およびリダイレクトとパイプラインの記述法を解説します。 -
4. 実践編:変数とスコープ・リスト操作
setコマンドによる変数管理、4種類のスコープ(ユニバーサル変数・グローバル・ローカル・エクスポート)、リスト(配列)の扱い、および$PATHの追加(fish_add_path)を解説します。 -
5. 実践編:制御構文と条件分岐・繰り返し
条件分岐(
if、switch)、繰り返し構文(for、while)、終了ステータスに基づく条件判定、およびtestコマンドの利用方法を解説します。 -
6. 実践編:関数・プロンプト・オートロード
関数の作成と遅延読み込み(オートロード機構)、プロンプトのカスタマイズ(
fish_prompt)、およびエイリアスよりも安全で便利な略語機能(abbr)を解説します。 -
7. 実践編:プラグイン管理とエコシステム
デファクトスタンダードのパッケージマネージャー「Fisher」の導入、定番プラグイン(Tide、z、bass 等)の活用法、および
config.fishの構成管理を解説します。 -
8. 応用編:POSIXシェルとの連携と共存
Bash/POSIX スクリプトとの棲み分け方針、
bassプラグインを用いた環境設定スクリプトの透過的ロード、および direnv との統合手法を解説します。 -
9. 応用編:イベントハンドラとカスタム補完
変数の変更やディレクトリ移動に反応するイベント駆動フック、および自作 CLI ツールやスクリプト向けの高度なタブ補完スクリプト(
complete)作成を解説します。 -
10. 応用編:パフォーマンスとベストプラクティス
起動速度の計測と最適化(プロファイリング)、設定の安全な移行とリセット、および保守性の高い fish スクリプトのコーディング指針を解説します。
入門編:Fishの概要と特徴・環境構築
fish(Friendly Interactive Shell)の基本設計、従来のシェルとの設計思想の違い、初期状態で利用できる先進機能、および導入手順を解説します。
fish とは何か
fish は、「設定不要で最初から最高の体験を提供する(Works out of the box)」ことを目指して設計された、対話操作(インタラクティブ)重視のスマートなコマンドラインシェルです。
Bash や Zsh では、便利な補完やシンタックスハイライト、履歴検索を実現するために、膨大な設定ファイル(.zshrc 等)を書いたり、多数のプラグインを導入して管理する必要がありました。
fish は、現代のコマンドライン作業に求められる強力な機能を標準で内蔵しており、インストールした瞬間から一切の設定作業なしで高度な作業環境が手に入ります。
主要な標準機能
プラグインなしで既定で有効になっている代表的な機能です。
-
リアルタイム・シンタックスハイライト: 入力中のコマンドがシステムに存在するかどうかを即座に判定します。有効なコマンドは青や緑で表示され、存在しないコマンドや構文エラーは赤色で警告されます。
-
自動入力サジェスト(Autosuggestions): 過去のコマンド履歴やカレントディレクトリの状況から、次に入力したい内容を薄い文字色で自動予測します。右矢印キー(
→)またはCtrl + Fを押すだけで全文を確定入力できます。 -
24ビット True Color 対応: 鮮やかなターミナルテーマやカラーリングをネイティブでサポートしています。
-
ウェブベースの設定画面(
fish_config): ブラウザ上でテーマの切り替えやプロンプトの選択、関数の確認が直感的に行えます。
Bash / Zsh との設計思想の違い
多くの Unix シェルは、1970 年代の Bourne Shell や POSIX 標準との後方互換性を何よりも優先しています。そのため、歴史的経緯による不自然な文法(スペースの有無によるエラー、難解なクォーティング規則など)が残されています。
fish はあえて POSIX 互換性を捨て、直感的で学習しやすく、一貫性のあるクリーンな文法をゼロから再設計しました。
現代のエンジニアリングでは、「システム起動や自動化スクリプトは標準の Bash/sh で記述し、人間がターミナルで対話操作するシェルには fish を使う」という合理的な使い分けが広く支持されています。
インストールとデフォルトシェルの設定
各プラットフォームにおける導入手順です。
» macOS への導入
Homebrew を使用して簡単に導入できます。
brew install fish
» Linux への導入
主要なディストリビューションの公式パッケージマネージャーからインストールできます。
# Ubuntu / Debian
sudo apt-get update
sudo apt-get install -y fish
# Fedora
sudo dnf install -y fish
# Arch Linux
sudo pacman -S fish
» 起動と既定シェルへの登録
ターミナルで fish と入力すると、即座に fish セッションが起動します。
ログイン時の既定シェルを fish に変更する場合は、以下の手順を実行します。
# /etc/shells に fish の実行パスが存在することを確認
command -v fish | sudo tee -a /etc/shells
# 既定シェルを fish に変更
chsh -s $(command -v fish)
入門編:インタラクティブ操作と基本機能
マニュアル自動解析に基づく高機能なタブ補完、履歴検索とオートサジェストの活用、Web ブラウザ設定 UI、およびキーバインドについて解説します。
タブ補完(Tab Completion)の威力
fish のタブ補完は、シェルの世界で最も先進的な機能の1つです。
コマンド名やファイル名だけでなく、コマンドのオプション(引数)まで詳細に補完されます。最大の特徴は、システムにインストールされている man ページ(マニュアル)を自動解析し、オプションの意味や説明文を補完候補の右側に一覧表示する点です。
# git switch と入力して Tab キーを押すと、利用可能なブランチ一覧と説明が表示される
git switch <Tab>
補完候補が複数ある場合、Tab キーや矢印キーを使って直感的に候補を選択できます。
» 補完データベースの更新
インストールした新しい CLI ツールの man ページから補完を生成・更新するには、以下のコマンドを実行します。
fish_update_completions
オートサジェストと履歴の活用法
文字を入力するたびに、過去の実行履歴から最適な候補がグレーの薄い文字色で自動提案(サジェスト)されます。
» サジェストの確定操作
- 全文確定(
→またはCtrl + F): 提案されている候補をすべて入力行に反映します。 - 単語確定(
Alt + →): 提案されている候補の次の1単語だけを確定します。長大なパスや引数の一部だけを再利用したい場合に便利です。
» 入力中文字列に基づく履歴検索
コマンドの一部を入力した状態で上矢印キー(↑)を押すと、その文字列で始まる過去の履歴だけをピンポイントで遡ることができます。
例えば docker run と入力してから ↑ を押すと、過去に実行した docker run コマンドだけが順に表示されます。
Web ベース設定 UI(fish_config)
fish には、ブラウザを通じてシェルの外観や動作を設定できる独自のツールが付属しています。
fish_config
コマンドを実行するとローカル Web サーバーが起動し、既定のブラウザで設定画面が開きます。
- Colors: 豊富なカラーテーマ(Dracula、Solarized、Nord 等)をプレビューしながらワンクリックで切り替え
- Prompt: 用意された多彩なプロンプトデザインの選択
- Functions / Variables / History: 現在定義されている関数や変数、履歴の閲覧
ターミナル側で Ctrl + C を押すと Web サーバーが安全に終了します。
キーバインドと操作モード
fish は既定で標準的な Emacs スタイルのキーバインドを採用しています。
| キー操作 | 役割 |
|---|---|
Ctrl + A / Ctrl + E | 行頭 / 行末へ移動 |
Alt + ← / Alt + → | 単語単位で前後に移動 |
Ctrl + K | カーソル位置から行末まで削除 |
Alt + D | カーソル位置の単語を削除 |
Ctrl + L | 画面をクリア |
Alt + H | 現在入力中のコマンドの man ページを即座に開く |
» Vi キーバインドへの切り替え
Vim の操作体系を好む場合は、設定により Vi モードへ切り替えることができます。
# Vi モードを有効化
fish_vi_key_bindings
# 既定(Emacs 風)に戻す場合
fish_default_key_bindings
入門編:Fish文法の基本とBashとの違い
Bash との意図的な構文の違い、クォーティングの仕組み、丸括弧を用いたコマンド置換、およびパイプラインとリダイレクトの基本文法を解説します。
Bash から移行する際の最重要の違い
fish は Bash や POSIX の歴史的制約を排除して設計されたため、基本構文に明確な違いがあります。
| 項目 | Bash / Zsh | fish |
|---|---|---|
| 変数への代入 | NAME="Alice" | set NAME "Alice" |
| コマンド置換 | $(date) または `date` | (date) |
| ブロックの終端 | fi, done, esac, } | すべて end で統一 |
| 外部環境変数 | export PATH=... | set -gx PATH ... |
| リスト(配列)展開 | "${arr[@]}" | $arr |
Bash の癖で VAR=value と入力すると、fish は「そのようなコマンドは存在しません」とエラーを出力します。
変数代入と参照の基本
fish では、変数の定義や変更にはすべて set コマンドを使用します。
# 変数に文字列を代入
set TARGET "Production"
# 変数の参照
echo "Deploying to $TARGET..."
# 変数の削除(未定義化)
set -e TARGET
変数名の直前にドル記号($)をつけて値を展開します。
コマンド置換(丸括弧構文)
コマンドの出力を別のコマンドの引数として渡す「コマンド置換」は、単純な丸括弧 (...) で行います。ドル記号は不要です。
# 現在の日付を取得してファイル名に埋め込む
tar -czf backup-(date +%Y%m%d).tar.gz ./data
# ファイル一覧をコマンド置換で渡す
count (ls -1 *.md)
丸括弧内の出力が改行で区切られている場合、fish はそれを自動的にリスト(配列)の各要素として解釈します。
クォーティングのルール
文字列の扱い方について説明します。
» ダブルクォート(“…”)
内部の変数は展開されます。ただし、Bash のように空白文字によって引数が勝手にバラバラに分割される現象(単語分割: Word Splitting)は起きません。1つの安全な引数として保持されます。
set GREETING "Hello World"
echo "$GREETING, Alice"
» シングルクォート(‘…’)
内部のすべての文字をそのままの文字として解釈します。変数や丸括弧によるコマンド置換は一切展開されません。
echo '$GREETING'
# 出力結果: $GREETING
パイプラインとリダイレクト
ストリームの受け渡しや保存の構文です。
» パイプライン(|)
左側の標準出力を右側の標準入力へ接続します。標準エラー出力をパイプで渡したい場合は 2>| を使用します。
# 通常のパイプライン
cat access.log | grep "ERROR" | wc -l
# エラー出力のみをパイプラインで渡す
build_project 2>| tee errors.log
» リダイレクト
標準的な記号(>、>>、<)を使用します。
# 出力をファイルに上書き
echo "Configuration" > config.txt
# 末尾に追記
echo "New Entry" >> config.txt
# エラー出力をファイルに保存
command_name 2> error.log
# 正常出力とエラー出力の両方を保存
command_name &> output_and_error.log
» 連続実行演算子(&& と ||)
fish 3.0 以降、一般的なシェルと同様に &&(成功時実行)と ||(失敗時実行)が完全にサポートされています。
make test && make deploy || echo "Build failed!"
実践編:変数とスコープ・リスト操作
fish 独自の強力な変数スコープ(ユニバーサル変数・グローバル・ローカル)、リスト(配列)の1始まりインデックス、および環境変数 $PATH の管理方法を解説します。
4つの変数スコープ
fish の変数は、有効範囲(スコープ)をオプションフラグで明示的に制御します。
» 1. ユニバーサル変数(-U / –universal)
fish の最も画期的な機能の1つです。ユニバーサル変数として設定された値は、実行中のすべての fish セッション(別ターミナルウィンドウ含む)へ即座に共有され、OS を再起動しても永続化 されます。
設定ファイル(config.fish)を編集することなく、ターミナルから直接一度実行するだけで永続的な環境設定が完了します。
# すべての端末で共通かつ永続的に有効なエディタ設定
set -Ux EDITOR nvim
» 2. グローバル変数(-g / –global)
現在のシェルプロセス全体で有効な変数です。他の端末や次回起動時のセッションには影響を与えません。
set -g PROJECT_ROOT "/home/user/project"
» 3. ローカル変数(-l / –local)
現在実行中のブロック(if、for)や関数内でのみ有効な一時変数です。ブロックを抜けると自動的に破棄されます。
set -l temp_name "temporary"
» 4. エクスポート(-x / –export)
変数を子プロセス(外部コマンド)に引き渡す「環境変数」にするには -x フラグを組み合わせます。
# グローバル環境変数としてエクスポート
set -gx NODE_ENV "production"
リスト(配列)の基本と操作
fish では、「すべての変数は内部的に文字列のリスト(要素の集まり)」として扱われます。単一の変数は、要素数が1つのリストに過ぎません。
» リストの作成
値を半角スペースで並べるだけでリストが生成されます。
# リストの作成
set colors red green blue
# 末尾に要素を追加(-a フラグ)
set -a colors yellow
» インデックス参照(1始まりの原則)
重要な注意点として、fish のインデックスは 1 から始まります(0 始まりの Bash や C 言語系と異なります)。
| 記法 | 意味 |
|---|---|
$colors[1] | 最初の要素(red) |
$colors[-1] | 最後の要素(yellow) |
$colors[2..3] | 2番目から3番目までのスライス(green blue) |
$colors[2..-1] | 2番目から末尾までのスライス |
» リストの要素数カウント
組み込みコマンド count を使用して要素数を取得します。
set items alpha beta gamma
count $items
# 出力結果: 3
$PATH の安全な管理(fish_add_path)
実行ファイルの検索パスである $PATH も、fish ではコロン区切りの文字列ではなく単なるリストとして管理されています。
パスを追加する際は、専用の組み込み関数 fish_add_path を使用するのが最も安全で推奨される方法です。
# PATH に新しいディレクトリを追加(重複は自動防止され、永続化される)
fish_add_path /opt/homebrew/bin
# 先頭ではなく末尾に追加したい場合
fish_add_path --append /usr/local/custom/bin
fish_add_path は、指定したディレクトリが既に $PATH に含まれているかを自動判定して二重登録を防ぎ、存在しない無効なパスの混入も回避します。
実践編:制御構文と条件分岐・繰り返し
終了ステータスに基づく条件判定、if や switch による分岐処理、for や while ループ、および math コマンドによる数値計算を解説します。
条件判定の基本思想
fish の制御構文では、条件式として直接「コマンド」を指定します。そのコマンドの終了ステータス($status)が 0(成功)であれば真、0 以外(失敗)であれば偽 と判定されます。
値の比較やファイルの存在確認を行うには、標準の組み込みコマンド test を使用します。
# ファイルが存在するか判定
if test -f ./config.yaml
echo "Config file exists."
end
test コマンドは角括弧 [ ... ] と同等ですが、fish では可読性の観点から test コマンドの明示的な記述が推奨されます。
条件分岐(if と switch)
直感的なブロック構文による分岐処理です。
» if / else if / else / end
Bash のような then や fi は不要で、すべて end でブロックを閉じます。
set -l response_code 200
if test $response_code -eq 200
echo "Success: OK"
else if test $response_code -eq 404
echo "Warning: Not Found"
else
echo "Unknown status code: $response_code"
end
» switch / case / end
文字列の一致やワイルドカードによるパターン分類には switch を使用します。
set -l target_env "staging"
switch $target_env
case "prod*"
echo "Danger: Production environment!"
case "stage" "staging"
echo "Info: Staging environment."
case "*"
echo "Info: Development or local environment."
end
繰り返し構文(for と while)
リストの走査や反復処理を行うループ構文です。
» for ループ
リストの各要素を順番に取り出して処理します。
set -l servers web01 web02 db01
for s in $servers
echo "Checking health of $s..."
end
# 連番の生成には seq コマンドを使用
for i in (seq 1 5)
echo "Step: $i"
end
» while ループ
指定したコマンドが成功(ステータス 0)を返し続ける間、処理を反復します。
# 外部コマンドから1行ずつ読み込んで処理
while read -l line
echo "Processing line: $line"
end < access.log
ループ内では break(ループの中断)や continue(次の反復へスキップ)が使用可能です。
算術計算(math コマンド)
fish は専用の算術展開記号(Bash の $(( ... )) 等)を持たず、組み込みの math コマンドを使用します。
math コマンドは整数の四則演算だけでなく、浮動小数点数(小数)の計算や数学関数の呼び出しにも標準で対応しています。
# 整数の計算
set total (math 10 + 20 \* 3)
echo "Total: $total"
# 小数の計算と四捨五入
set result (math "3.14159 * 2.5")
echo "Result: $result"
# べき乗や関数
math "sqrt(144)"
# 出力結果: 12
実践編:関数・プロンプト・オートロード
fish の高速起動を支える関数のオートロード機構、プロンプトのカスタマイズ手法、およびエイリアスを進化させた略語機能(abbr)を解説します。
関数の定義と引数の扱い
fish における関数は function キーワードで定義し、end で閉じます。
関数に渡された引数は、すべて $argv というリスト変数に格納されます。Bash のような $1 や $2 ではなく、$argv[1] や $argv[2] としてアクセスします。
function greet
set -l name $argv[1]
if test -z "$name"
set name "Guest"
end
echo "Hello, $name!"
end
# 呼び出し
greet Alice
$argv は通常のリストであるため、count $argv による引数の個数取得や、for arg in $argv による走査が容易に行えます。
オートロード機構(遅延読み込み)
Bash や Zsh では、設定ファイル(.bashrc 等)に多数の関数や設定を記述するほどシェルの起動時間が遅くなります。
fish では、起動時にすべての関数をメモリに読み込むことはしません。ディレクトリ ~/.config/fish/functions/ 配下に「関数名.fish」というファイル名で保存しておくと、そのコマンドが実際にターミナルで呼び出された瞬間に自動で読み込まれます。
この仕組みにより、何千もの自作関数やツールを定義していても、fish の起動速度は常にミリ秒単位の超高速を維持できます。
» funcsave コマンド
ターミナルで定義した関数を即座にオートロード用ファイルとして保存できます。
# 定義した関数を ~/.config/fish/functions/greet.fish に自動保存
funcsave greet
プロンプトのカスタマイズ
fish のプロンプトは、通常の関数(fish_prompt)として定義されています。
» 左プロンプト(fish_prompt)
ターミナルの左側に表示される基本プロンプトです。set_color コマンドで文字色を装飾し、set_color normal でリセットするのが標準的な作法です。
function fish_prompt
set_color cyan
echo -n (prompt_pwd) # 短縮されたカレントディレクトリ
set_color green
echo -n " > "
set_color normal
end
» 右プロンプト(fish_right_prompt)
画面の右端に時刻や Git ブランチ名などを表示できます。入力中のコマンドが右端に近づくと、文字が重ならないよう自動的に非表示になります。
function fish_right_prompt
set_color 888888
echo -n (date "+%H:%M:%S")
set_color normal
end
エイリアス(alias)と略語(abbr)
fish には、コマンドの短縮入力手段として alias と abbr の2つが用意されています。
» alias
入力したコマンドを別のコマンドに置き換える従来の仕組みです。内部的には小さな関数として定義されます。
alias ll="ls -la"
» abbr(略語機能:fish 推奨)
fish で強く推奨されるのが「略語(Abbreviation)」機能です。ターミナルで略語を入力してスペースキーや Enter キーを押すと、入力行の上で即座に正式なコマンドへ自動展開 されます。
# Git コマンドの略語登録
abbr -a gco "git checkout"
abbr -a gp "git push"
abbr -a gst "git status"
» abbr の優れたメリット
- 履歴の透明性: コマンド履歴には展開後の完全なコマンド(
git checkout等)が保存されるため、後から履歴を検索しやすくなります。 - 共同作業での安心感: 画面共有やペアプログラミング中に独自のエイリアスで他者を混乱させることがありません。
- スクリプトへの転用: 画面に表示された通りのコマンドをそのままスクリプトに貼り付けて利用できます。
実践編:プラグイン管理とエコシステム
fish のデファクトスタンダードであるパッケージマネージャー「Fisher」の導入、開発効率を高める定番プラグイン、および設定ファイル config.fish の整理手法を解説します。
パッケージマネージャー Fisher の導入
fish には標準でプラグイン機能の土台がありますが、外部のテーマや拡張機能を簡単に管理するために「Fisher」を利用するのが一般的です。
Fisher はシェルスクリプトのみで実装されており、余計な依存関係がなく極めて軽量・高速に動作します。
» Fisher のインストール
ターミナルで以下のコマンドを実行するだけでインストールが完了します。
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher
» 基本的なコマンド操作
# GitHub リポジトリ名を指定してプラグインをインストール
fisher install jethrokuan/z
# インストール済みプラグインの一覧表示
fisher list
# 全プラグインを最新バージョンに一括更新
fisher update
# プラグインの削除
fisher remove jethrokuan/z
インストールしたプラグインの一覧は ~/.config/fish/fish_plugins に自動記録されます。このファイルを Git(dotfiles リポジトリ等)で管理しておけば、新しいマシンでも fisher update を実行するだけで全く同じ環境を再現できます。
開発を加速する定番プラグイン
世界中の開発者に愛用されている代表的なプラグインです。
» 1. IlanCosman/tide(モダンプロンプト)
Rust や C++ に匹敵する表示速度を誇る高機能プロンプトです。対話型のウィザード(tide configure)を実行することで、好みのデザインやアイコンスタイルを簡単に設定できます。
fisher install IlanCosman/tide@v6
tide configure
» 2. jethrokuan/z(高速ディレクトリジャンプ)
頻繁に利用するディレクトリの履歴を自動学習し、短いキーワードだけで目的のフォルダへ移動(cd)できるようにするツールです。
fisher install jethrokuan/z
# 例: 以前アクセスした /var/www/my-project へ瞬時に移動
z my-proj
» 3. edc/bass(POSIX 互換ブリッジ)
Bash 用に書かれた環境構築スクリプト(例: source /opt/tool/env.sh)を一時的な Bash サブプロセスで実行し、変更された環境変数だけを現在の fish セッションへ反映する重要プラグインです。
fisher install edc/bass
» 4. patrickf1/fzf.fish(あいまい検索の統合)
コマンド履歴、ファイルパス、Git コミットなどを fzf のインタラクティブなあいまい検索と連携させます。
fisher install patrickf1/fzf.fish
config.fish の設計方針
fish のユーザー設定ファイルは ~/.config/fish/config.fish に配置します。
設定ファイルを肥大化させず、起動速度を保つためのベストプラクティスです。
# ~/.config/fish/config.fish
# 1. 対話的セッションでのみ実行したい処理を限定する
if status is-interactive
# 略語の登録
abbr -a g "git"
abbr -a k "kubectl"
# キーバインドの設定など
end
# 2. 環境変数の設定はユニバーサル変数(set -Ux)を優先し、
# 頻繁に再評価が必要なものだけを config.fish に記述する
status is-interactive で囲むことにより、SCP や非対話的スクリプト実行時に余計な処理が走るのを防ぐことができます。
応用編:POSIXシェルとの連携と共存
Bash や POSIX 標準スクリプトとの共存方針、bass プラグインを用いた環境設定の取り込み、およびモダンな開発ツールとの統合手法を解説します。
スクリプトと対話環境の棲み分け方針
fish を導入した際に最も重要な原則は、「対話操作には fish を使い、共有スクリプトには Bash/POSIX を使う」 という役割の分離です。
- 共有スクリプト(
.sh): CI/CD パイプライン、Docker コンテナ、チーム開発で共有するスクリプトには、常に#!/usr/bin/env bashまたは#!/bin/shを指定します。どのサーバーや開発者環境でも確実に動作することを最優先します。 - スクリプトの実行:
fish のターミナルから
./deploy.shやbash script.shを呼び出せば、シバンに従って自動的に Bash が立ち上がって実行されるため、何の問題もありません。
Bash スクリプトの読み込み(bass プラグイン)
SDK やミドルウェアのセットアップでは、「source env.sh を実行して環境変数を設定してください」と指示されるケースが多々あります。
このスクリプトには Bash の構文(export VAR=... 等)が含まれているため、fish の source コマンドで直接読み込むと構文エラーになります。
この問題を解決するのがプラグイン「bass」です。
# bass コマンド経由で Bash スクリプトを実行
bass source /opt/intel/oneapi/setvars.sh
# 引数付きの Bash コマンドを実行して環境を引き継ぐ
bass export AWS_PROFILE=staging
bass は内部で一度 Bash プロセスを起動してスクリプトを評価し、実行前後で変化した環境変数のみを抽出して現在の fish セッションに安全に適用します。
ツール初期化とフック(eval の代替)
多くの現代的な開発ツール(mise, starship, zoxide, direnv 等)は、シェルの起動時に初期化スクリプトを出力して読み込ませる構成をとります。
Bash では eval "$(tool init bash)" と書くパターンですが、fish ではパイプと source コマンドを組み合わせて直感的に記述します。
» 主要ツールの設定例(config.fish 内)
# mise(開発環境・ランタイムマネージャー)の有効化
mise activate fish | source
# Starship プロンプトの初期化
starship init fish | source
# zoxide(高速 cd ツール)の初期化
zoxide init fish | source
direnv によるディレクトリ単位の環境変数切り替え
プロジェクトごとに異なる環境変数を自動でロードする direnv も、fish と完全に統合できます。
# ~/.config/fish/config.fish
direnv hook fish | source
プロジェクトルートに .envrc(Bash 構文)を配置しておけば、ディレクトリに移動(cd)した瞬間に自動的に環境変数が適用され、ディレクトリから抜けると元に戻ります。
応用編:イベントハンドラとカスタム補完
変数の変更やシェル終了などに連動するイベント駆動フック、および自作コマンド向けのインテリジェントなタブ補完定義(complete)の作成方法を解説します。
イベントハンドラ(Event Handler)の仕組み
fish には、シェルの特定のライフサイクルや変数の変動を検知して関数を自動起動する「イベント駆動モデル」が組み込まれています。
関数を定義する際に、イベント指定オプションを付与します。
» 1. 変数の変更を監視(–on-variable)
指定した変数の値が書き換わった瞬間に処理を実行します。例えばカレントディレクトリ($PWD)を監視して、ディレクトリ移動のたびに自動処理を行えます。
function on_pwd_change --on-variable PWD
# Git リポジトリ内であれば簡易ステータスを表示
if test -d .git
git status --short
end
end
» 2. イベントの発火を監視(–on-event)
特定の内部イベントが発生したときに実行されます。
| イベント名 | 発生タイミング |
|---|---|
fish_prompt | プロンプトが表示される直前 |
fish_postexec | ユーザーが入力したコマンドの実行が完了した直後 |
fish_exit | シェルが終了するとき(一時ファイルのクリーンアップ等) |
# 長時間かかったコマンドの終了時に実行時間を表示
function notify_long_command --on-event fish_postexec
set -l duration $CMD_DURATION # コマンドの実行時間(ミリ秒)
if test $duration -gt 10000
set -l sec (math "$duration / 1000")
echo "[Notice] Command took $sec seconds to finish."
end
end
自作コマンドのタブ補完(complete)
fish では、自作のスクリプトやツールに対しても、標準コマンドと全く同じ高品質なタブ補完(説明文付き)を簡単に追加できます。
補完スクリプトは ~/.config/fish/completions/<コマンド名>.fish に配置しておくと、必要になった瞬間にオートロードされます。
» complete コマンドの基本構文
# ~/.config/fish/completions/mytool.fish
# 1. 短いオプション (-v) と長いオプション (--verbose) の定義
complete -c mytool -s v -l verbose -d "詳細なログを出力する"
# 2. 値を要求するオプション (--env) と固定候補の提示
complete -c mytool -l env -x -a "development staging production" -d "対象の環境を指定"
# 3. 引数としてファイルではなく特定の文字列だけを補完させる (-f)
complete -c mytool -s h -l help -f -d "ヘルプを表示する"
» 主要なオプションの意味
-c <cmd>: 補完対象のコマンド名-s <char>: 短いオプション(ハイフン1文字)-l <name>: 長いオプション(ハイフン2文字)-d <text>: 補完一覧に表示される説明文(Description)-a <candidates>: 補完候補として表示する文字列(またはコマンド置換(cmd))-f: ファイル名補完を無効化(コマンド独自の固定引数のみを表示したい場合)
独自の補完を定義することで、チーム内ツールの利用ミスを劇的に減らし、操作性を向上させることができます。
応用編:パフォーマンスとベストプラクティス
起動速度のプロファイリングと高速化、設定ファイルの管理とリカバリー、および保守性の高い fish スクリプトを作成するためのコーディング規約を解説します。
起動速度のプロファイリングと最適化
fish の起動が重く感じられる場合、組み込みのプロファイリング機能を用いてどの処理に時間がかかっているかを正確に計測できます。
# 起動プロファイルを startup.log に記録して終了
fish --profile-startup startup.log -i -c exit
# 実行時間順にソートしてボトルネックを調査
sort -nk2 startup.log | tail -n 20
» 起動時間を短縮するための改善ポイント
- 外部コマンド呼び出しの削減:
config.fishのトップレベルでgrepやawk、nodeなどの外部コマンドを何度も呼び出すと、プロセスの生成コストで起動が数百ミリ秒遅延します。 - オートロード(functions/)の徹底:
関数は
config.fishに直接長く書くのではなく、~/.config/fish/functions/配下の個別ファイルに分割し、実際に呼び出されるまで読み込まない設計にします。 - 重いツールの遅延初期化: 頻繁に使わない CLI ツールの初期化コードは、専用の関数内で呼び出された初回にのみ初期化するラッパー関数にするなどの工夫が有効です。
設定ファイルの構成とリカバリー
fish の設定ファイルはすべて標準的な XDG ディレクトリ(~/.config/fish/)配下に集約されています。
~/.config/fish/
├── config.fish # ユーザー設定エントリーポイント
├── fish_plugins # Fisher で管理されているプラグイン一覧
├── fish_variables # ユニバーサル変数(set -U)の実体データ
├── functions/ # オートロードされる自作関数群
└── completions/ # オートロードされるカスタム補完スクリプト
» 不具合時のクリーン起動(–no-config)
プラグインの不整合や構文エラーによって fish が起動しなくなった場合は、設定ファイルの読み込みを完全にスキップして素の状態で起動できます。
fish --no-config
また、設定したユニバーサル変数をすべて初期化したい場合は、~/.config/fish/fish_variables をバックアップした上で削除してシェルを再起動します。
スクリプト作成のベストプラクティス
共同開発や個人運用でトラブルを起こさないための規約です。
» 1. コマンドの存在確認には type -q を使用する
外部ツールがインストールされているか判定する際は、出力を抑制する -q(quiet)オプションを指定した type コマンドを使用します。
if not type -q git
echo "Error: git is not installed."
return 1
end
» 2. 変数宣言時のスコープ明示
関数内やブロック内で変数を定義する際は、スコープフラグ(-l または -g)の省略を避け、必ず明示します。
# 良い例: ローカル変数を明示
set -l current_user (whoami)
# 避けるべき例: スコープが曖昧
set current_user (whoami)
» 3. 関数には必ず説明文(–description)をつける
関数を定義する際は、--description 引数で役割を明記します。これにより、functions my_func で概要を確認でき、タブ補完時にも説明文が自動表示されます。
function clean_logs --description "古いログファイルを削除して空き容量を確保する"
rm -rf ./logs/*.log
end