チュートリアル

なぜfishなのか?

fishはbashやzshのように完備で, 気の利いたユーザーフレンドリーなコマンドラインシェルです. fishはシンタックスハイライト, オートサジェスト, タブ補完といった強力な機能を学習したり 設定をいじったりすることなく利用することができます.

コマンドラインを難しい構文を覚えたり設定ファイルを書いたりすることなくもっと生産的に, 便利に, 楽しくしたいならfishこそが探し求めていたものになるでしょう!

はじめかた

一度インストールしてしまえば今使っているシェルでfishとタイプするだけで試してみることができます!

起動するとfishのプロンプトが表示されます. これはもう準備ができていてfishを始めることができることを意味しています.

> fish
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
you@hostname ~>____

このプロンプトはfishのデフォルトのプロンプトで, あなたのユーザーネーム, ホストネーム, それからワーキングディレクトリを表示しています.

  • プロンプトを変えるためには[プロンプトの変えかた]
  • fishをログインシェルにするには[デフォルトシェルをfishに変える]

を読んでください.

以降, プロンプトは簡単のため'>_'で表します.

fishを学ぶ

このチュートリアルではコマンドラインシェルとUnixコマンドの基本的な理解と, fishが動く環境を前提としています.

もし他のシェルのことをよく知っていて, fishがそれとどう異なるのかを知りたい場合は他のシェルと違ってというフレーズを検索してください. これは重要な違いを示す時に使われています.

コマンドの実行

fishは他のシェルと同じように, コマンドに続けて引数を与えることで実行します. スペースはセパレータとなっています.

>_ echo hello world
hello world

空白文字として引数を与えたい場合, バックスラッシュを前置するか或いはシングルクオート, ダブルクオートで囲むことによって実現します.

>_ mkdir My\ Files
>_ cp ~/Some\ File 'My Files'
>_ ls "My Files"
Some File

コマンドはセミコロンを用いることによって繋げることができます.

ヘルプを読む

fishには素晴らしいhelpとmanページが備わっています. helpコマンドを実行するとウェブブラウザでヘルプを開き, manコマンドはターミナル上でmanページを開きます. 特定のコマンドについてのヘルプを読むこともでき, 例えばhelp setとすればウェブブラウザで, mans setとすればターミナルで読むことができます.

>_ man set
set - handle shell variables
  Synopsis...

シンタックスハイライト

fishを使っているとタイプするに従ってシンタックスハイライトが効いていることに すぐに気がつくでしょう. 無効なコマンドはデフォルトでは赤く表示されます.

>_ <eror>/bin/mkd</eror>

コマンドが存在しない或いは実行可能でない場合に無効となり, 有効になると色が変化します.

>_ /bin/mkdir

fishはファイルパスが有効なとき下線を示すでしょう.

>_ cat <u>~/somefi</u>___

これは'somefi'から始まるファイルが存在していることを示していて, タイピングの補助となります.

これらのシンタックスハイライトは他にもたくさんありますが, fish_configを変更したり 変数を直接編集することによって色を変えることができます.

ワイルドカード

fishはワイルドカードの*をサポートしています. 全てのJPEGファイルをリストアップするには次のようにします.

>_ ls *.jpg
lena.jpg
meena.jpg
santa maria.jpg

複数のワイルドカードを用いることもできます.

>_ ls l*.p*
lena.png
lesson.pdf

特に強力なのはディレクトリを再帰的に探索する**です.

>_ ls /var/**.log
/var/log/system.log
/var/run/sntp.log

ディレクトリの探査に時間がかかるときはCtrl-cで中止することができます.

パイプとリダイレクト

|を用いることでコマンドをパイプすることができます.

>_ echo hello world | wc
       1       2      12

stdinとstdoutは馴染み深い<>によってリダイレクトすることができます. stderrは2>によってリダイレクトされます.

>_ grep fish < /etc/shells > ~/output.txt 2> ~/errors.txt

オートサジェスト

fishはタイプに従ってコマンドをサジェストします. サジェストされた結果はカーソルの右側に灰色で示されます.

>_ <eror>/bin/h</eror><s>___ostname</s>

パスやオプションをサジェストすることもできます.

>_ grep --i<s>___gnore-case</s>

もちろん履歴にもはたらきます. 一度コマンドを実行したことがあれば, 数文字タイプしただけで再度 実行することができます.

>_ <eror>r<</eror><s>___sync -avze ssh . myname@somelonghost.com:/some/long/path/doo/dee/doo/dee/doo</s>

サジェストの結果を利用するにはまたはCtrl-fを押してください. 最初の1語だけを利用したい場合はAlt-→を押してください. また, サジェストが求めているものと異なればそのまま無視して構いません.

タブ補完

fishはすぐに使えるリッチなタブ補完を備えています. tabを押してみると, fishはコマンドや引数, パスを補完しようとするでしょう.

>_ <eror>/pri</eror> :kbd:`Tab` => /private

複数の候補が見つかれば, それらをリストとして表示します.

>_ <eror>~/stuff/s</eror> :kbd:`Tab`
<mtch>~/stuff/script.sh  <i>(Executable, 4.8kB)</i>  \mtch{~/stuff/s</mtch>ources/  <i>(Directory)</i>}

tabを押すたびにその候補を順にフォーカスします.

fishはgitのブランチのようなものまでも補完することができます.

>_ git merge pr :kbd:`Tab` => git merge prompt_designer
>_ git checkout b :kbd:`Tab`
<mtch>builtin_list_io_merge <i>(Branch)</i> \mtch{b</mtch>uiltin_set_color <i>(Branch)</i> <mtch>b</mtch>usted_events <i>(Tag)</i>}

実際にtabを押して確認してみましょう!

変数

他のシェルと同じように, $によって変数を扱います.

>_ echo My home directory is $HOME
My home directory is /home/tutorial

変数はダブルクオートのなかでは置換されますが, シングルクオートの中では置換されません.

>_ echo "My current directory is $PWD"
My current directory is /home/tutorial
>_ echo 'My current directory is $PWD'
My current directory is $PWD

他のシェルと違って, fishは変数を代入する構文を持ちません. 代わりに変数名とその値を引数にとる, setコマンドを持ちます.

>_ set name 'Mister Noodle'
>_ echo $name
Mister Noodle

(クオートに注意してください. もしこれがなければMisterNoodleは別々の引数として認識され, $nameは2つの要素を持つリストになります.)

他のシェルと違って, 変数は置換後に分割されることはありません.

>_ mkdir $name
>_ ls
Mister Noodle

bashでは上記コマンドで"Mister"と"Noodle"という2つのディレクトリが作られます. fishでは"Mister Noodle"という値を持った変数によって1つのディレクトリが作られます. つまりmkdirにはスペースを含んだ文字列の引数として渡されます. 他のシェルではリストという表現ではなく"配列"という用語が用いられます.

終了ステータス

他のシェルと違って, fishは直前に実行したコマンドの終了ステータスを$?ではなく$statusという変数に格納します.

>_ false
>_ echo $status
1

0は成功, それ以外はエラーを表します. $pipestatusというパイプの過程の終了ステータスを格納する配列の変数もあります.

エクスポート(シェル変数)

他のシェルと違って, fishexportコマンドをサポートしていません. 代わりにsetコマンドの--export或いは-xオプションによって変数をエクスポートします.

>_ set -x MyVariable SomeValue
>_ env | grep MyVariable
MyVariable=SomeValue

変数は-e若しくは--eraseオプションによって削除することができます.

>_ set -e MyVariable
>_ env | grep MyVariable
(no output)

リスト

先に見たsetコマンドはクオートで囲むことによってMister Noodleを1つの引数として扱いました. もし2つの引数だったなら, 変数nameは長さ2のリストになります. 実際, fishの全ての変数はリストであり, いくつでも値を保持できるし全く持たないことも可能です.

$PWDのようないくつかの変数は1つしか値を持ちません. 慣習に従って変数の値というとき, 最初(かつただ1つ)の値を指すことにします.

$PATHのようなその他の変数は複数の値を保持しています. これらの変数は複数の引数として展開されます.

>_ echo $PATH
/usr/bin /bin /usr/sbin /sbin /usr/local/bin

"PATH"で終わる変数は自動的にコロンで分割されてリストになります. これらはサブコマンドに渡されるときにコロンによって結合されます. この仕様は$PATHはコロンで区切られていると想定している他のツールとの互換性のためにあります. 明示的にパスを変数に加えるにはset --path, 削除するにはset --unpathを用いることができます.

リストは要素として他のリストを保持することはできず, 再帰的ではありません. 変数は文字列のリストであり, 他にはありえません

リストの要素数を得るにはcountコマンドを使います.

>_ count $PATH
5

リスト自身に追加の引数をセットすることで, 要素を追加することができます. $PATH/usr/local/binを追加する例を示します.

>_ set PATH $PATH /usr/local/bin

[]を用いることで個別の要素にアクセスすることができます. インデックスは1から始まり, 最後は-1です.

>_ echo $PATH
/usr/bin /bin /usr/sbin /sbin /usr/local/bin
>_ echo $PATH[1]
/usr/bin
>_ echo $PATH[-1]
/usr/local/bin

"スライス"を用いてある範囲の要素にアクセスすることもできます.

>_ echo $PATH[1..2]
/usr/bin /bin
>_ echo $PATH[-1..2]
/usr/local/bin /sbin /usr/sbin /bin

forループを用いてリスト全体(或いはスライス)に繰り返しアクセスすることもできます.

>_ for val in $PATH
     echo "entry: $val"
   end
entry: /usr/bin/
entry: /bin
entry: /usr/sbin
entry: /sbin
entry: /usr/local/bin

他のリストや文字列と隣り合ったリストは, クオートで囲まなければ直積となります. ([直積], [変数展開] 参照)

>_ set a 1 2 3
>_ set 1 a b c
>_ echo $a$1
1a 2a 3a 1b 2b 3b 1c 2c 3c
>_ echo $a" banana"
1 banana 2 banana 3 banana
>_ echo "$a banana"
1 2 3 banana

これは[ブレース展開]と似た作用です.

コマンド置換

コマンド置換は1つのコマンドの実行結果を他のコマンドの引数として渡す際に使われます. 他のシェルと違って, fish``ではなく()を用います.

>_ echo In (pwd), running (uname)
In /home/tutorial, running FreeBSD

コマンドの結果を変数に代入するときによく使われます.

>_ set os (uname)
>_ echo $os
Linux

コマンド置換はクオートによって展開されません. その代わり一度クオートを閉じ, コマンド置換を行いそれから再びクオートを開くことによって実現できます.

>_ touch "testing_"(date +%s)".txt"
>_ ls *.txt
testing_1360099791.txt

他のシェルと違って, fishは(スペースやタブのような)いかなる空白文字であっても 分割されることはなく, 改行によってのみ分割されます. これはpkg-configのような複数の引数を1行に出力するコマンドを使う際に問題となります. スペースでも分割できるようにするためにはstring splitを用いてください.

>_ printf '%s\n' (pkg-config --libs gio-2.0)
-lgio-2.0 -lgobject-2.0 -lglib-2.0
>_ printf '%s\n' (pkg-config --libs gio-2.0 | string split " ")
-lgio-2.0
-lgobject-2.0
-lglib-2.0

セパレートコマンド(;)

他のシェルと違って, fishは複数のコマンドを独立した行に書くことも同一の行に書くことも許容されます.

ワンライナーで書く場合, ;を用います. 以下の2つの例が等価であることを確認してください.

echo fish; echo chips

# or
echo fish
echo chips

コンバイナ(and, or, not)

fishは馴染みのある&&||, それから否定の!をサポートしています.

>_ ./configure && make && sudo make install

さらにfishand, ornotも同様にサポートしています. 最初の2つはコマンドの修飾子で, 優先順位は低くなっています. 以下に例を挙げます.

>_ cp file1.txt file1_bak.txt && cp file2.txt file2_bak.txt ; and echo "Backup successful"; or echo "Backup failed"
Backup failed

セパレートコマンド(;)の項で触れたように複数行にわたって 書くこともできます.

cp file1.txt file1_bak.txt && cp file2.txt file2_bak.txt
and echo "Backup successful"
or echo "Backup failed"

条件式(if, else, switch)

if, else ifそれからelseを使うことでコマンドの終了ステータスによって 実行するコードを条件分岐することができます.

if grep fish /etc/shells
    echo Found fish
else if grep bash /etc/shells
    echo Found bash
else
    echo Got nothing
end

文字列や数字の比較, ファイルのプロパティ(ファイルが存在するか, 書き込み可能かなど)を確認する場合には次のように[testコマンド]を利用してください.

if test "$fish" = "flounder"
    echo FLOUNDER
end

# or

if test "$number" -gt 5
    echo $number is greater than five
else
    echo $number is five or less
end

コンバイナを使うことでさらに複雑な条件式がかけるようになります.

if grep fish /etc/shells; and command -sq fish
    echo fish is installed and configured
end

もっと複雑になったときにはbeginendを使ってグループ化してください.

また, switchコマンドもあります.

switch (uname)
case Linux
    echo Hi Tux!
case Darwin
    echo Hi Hexley!
case FreeBSD NetBSD DragonFly
    echo Hi Beastie!
case '*'
    echo Hi, stranger!
end

caseはフォールスルーせず, さらに複数の引数やクオートで囲まれたワイルドカードを受け付けることに注意してください.

関数

fishの関数はコマンドのリストであり, オプションとして引数をとることができます. 他のシェルと違って, 引数は$1のような"数字変数"ではなく,$argvという一つのリストとして渡されます. 関数を作るためにビルトインのfunctionコマンドを用います.

>_ function say_hello
     echo Hello $argv
   end
>_ say_hello
Hello
>_ say_hello everybody!
Hello everybody!

他のシェルと違って, fishはエイリアスや特殊なプロンプト構文を持ちません. これらも関数で表現します.

functionsキーワードによって全ての関数名を列挙することができます. (複数形であることに注意!) fishにははじめから数多くの関数が定義されています.

>_ functions
alias, cd, delete-or-exit, dirh, dirs, down-or-search, eval, export, fish_command_not_found_setup, fish_config, fish_default_key_bindings, fish_prompt, fish_right_prompt, fish_sigtrap_handler, fish_update_completions, funced, funcsave, grep, help, history, isatty, ls, man, math, nextd, nextd-or-forward-word, open, popd, prevd, prevd-or-backward-word, prompt_pwd, psub, pushd, seq, setenv, trap, type, umask, up-or-search, vared

functionsに関数名を渡すことでその関数の中身をみることもできます.

>_ functions ls
function ls --description 'List contents of directory'
    command ls -G $argv
end

ループ

Whileループは次のように使えます.

>_ while true
     echo "Loop forever"
end
Loop forever
Loop forever
Loop forever
...

Forループはリスト全体を処理することができます.

>_ for file in *.txt
     cp $file $file.bak
   end

seqコマンドを用いることで数列でループすることができます.

>_ for x in (seq 5)
     touch file_$x.txt
   end

プロンプト

他のシェルと違って, PS1のようなプロンプト変数はありません. プロンプトを表示するために, fishfish_promptという名前の関数を実行し, その出力がプロンプトとして用いられます.

次のように独自のプロンプトを定義することができます.

>_ function fish_prompt
     echo "New Prompt % "
   end
New Prompt %

複数行のプロンプトも可能です. 色はset_colorコマンドにANSI colorsか16進数のRGB値を渡すことによって設定できます.

>_ function fish_prompt
     set_color purple
     date "+%m/%d/%y"
     set_color FF0
     echo (pwd) '>'
     set_color normal
   end
<span style="color: purple">02/06/13</span>
<span style="color: #FF0">/home/tutorial ></span>___

fish_config_prompt関数を実行することでサンプルの中からプロンプトを選ぶことができます. また, fishfish_right_prompt関数によって右プロンプトもサポートしています.

PATH変数

$PATHは環境変数で, fishがコマンドを探索するディレクトリを保持しています. 他のシェルと違って, $PATHリストであり, コロンで区切られた文字列ではありません.

/usr/local/bin/usr/sbin$PATHに追加するためには次のように書きます.

>_ set PATH /usr/local/bin /usr/sbin $PATH

$PATHから/usr/local/binを削除するには次のようにします.

>_ set PATH (string match -v /usr/local/bin $PATH)

また, 他のシェルの.profileのようにconfig.fishを直接編集しても構いません.

より早い方法として$fish_user_pathsという[ユニバーサル変数]を設定すると良いでしょう. これは自動的に$PATHに追加されます. 例えば, $PATHに永続的に/usr/local/binを追加したい場合, 次のようにしてください.

>_ set -U fish_user_paths /usr/local/bin $fish_user_paths

この方法の利点は設定ファイルを汚さなくてよいところです. 一度コマンドラインで実行さえすれば現在のセッションから永久的にパスが有効になります. (注意: これをconfig.fishに書き加えないでください. もしそうした場合, fishを起動するたびに変数に追加されて長くなっていってしまいます!)

起動に際して(.bashrc)

fish~/.config/fish/config.fishに書かれたコマンドを起動時に実行します. もしこのファイルがなかったら新たに作ることができます.

次のようなコマンドを用いる事でconfig.fishに直接関数や変数を定義することができます.

>_ cat ~/.config/fish/config.fish

set -x PATH $PATH /sbin/

function ll
    ls -lh $argv
end

しかし, オートロード関数やユニバーサル変数を使うのが一般的で効果的です.

オートロード関数

fishがコマンドを認識したとき, ~/.config/fish/functions/からそのコマンドを探し, オートロード関数として呼び出そうとします.

例えばllという関数が欲しければ, ll.fishというテキストファイルを~/.config/fish/functions/に追加します.

>_ cat ~/.config/fish/functions/ll.fish
function ll
    ls -lh $argv
end

同様に独自プロンプトを次のように定義するのがより良い方法です.

>_ cat ~/.config/fish/functions/fish_prompt.fish
function fish_prompt
    echo (pwd) "> "
end

こうしたファイルを自動的に作る方法として[funced], [funcsave]を参考にしてください.

ユニバーサル変数

ユニバーサル変数はfishの全てのインスタンスで値が共有される変数で, 現在立ち上げているインスタンスだけでなくリブートした後でさえ継続します. set -Uのオプションを用いることでユニバーサル変数を設定することができます.

>_ set -U EDITOR vim

上記コマンドを実行した後, 他のインスタンスにも引き継がれます.

>_ echo $EDITOR
vim

fishをデフォルトシェルにする

fish(或いはその他のシェル)をデフォルトシェルとして使いたい場合, fishの実行ファイル/usr/local/bin/fish/etc/shellsにも置く必要があります. それからchsh -s /usr/local/bin/fishでデフォルトシェルに変更することができます.

具体的には次のコマンドに従ってください.

fishを/etc/shellsに追加する.

> echo /usr/local/bin/fish | sudo tee -a /etc/shells

デフォルトシェルをfishに変える.

> chsh -s /usr/local/bin/fish

(他のシェルに戻すには上記コマンドの引数/usr/local/bin/fish/bin/bash, /bin/tcsh/bin/zshに置き換えてください.)

より多くを知るには

もっとfishについて知りたければより詳しい[ドキュメント]や 公式メーリングリスト, irc.oftc.netのIRCチャンネル#fish, github pageを参照してください.