fish言語¶
この文書はfishのスクリプト言語の包括的な概要です。
インタラクティブ機能については、 Interactive use を参照してください。
構文の概要¶
fishのようなシェルはコマンドを与えることで使用されます。コマンドは、コマンド名の後に引数を続けて記述することで実行されます。例えば:
echo hello world
echo コマンドは引数を画面に出力します。この例では出力は hello world です。
fishではすべてコマンドで実行されます。他のコマンドを繰り返すコマンド、変数を代入するコマンド、複数のコマンドを1つのコマンドとして扱うコマンドなどがあります。これらのコマンドはすべて同じ基本構文に従います。
コンピュータ上のすべてのプログラムは、fishのコマンドとして使用できます。プログラムファイルが PATH ディレクトリのいずれかにある場合は、プログラム名を入力するだけで使用できます。そうでない場合は、ディレクトリを含むファイル名全体(/home/me/code/checkers/checkers や ../checkers など)が必要です。
ここにいくつかの便利なコマンドのリストがあります:
cd: 現在のディレクトリを変更する
ls: ファイルとディレクトリの一覧を表示するman: マニュアルページを表示します。man lsで「ls」コマンドのヘルプを表示するか、man mvで「mv」に関する情報を表示します。mv: ファイルを移動(名前変更)するcp: ファイルをコピーするopen: 各ファイルタイプに関連付けられたデフォルトのアプリケーションでファイルを開く
less: ファイルの内容を表示する
コマンドと引数はスペース文字 `` `` で区切られます。すべてのコマンドは、改行(リターンキーを押す)またはセミコロン ; で終わります。セミコロンで区切ることで、同じ行に複数のコマンドを記述できます。
スイッチは非常に一般的な特殊引数です。スイッチはほとんどの場合、1つ以上のハイフン - で始まり、コマンドの動作を変更します。例えば、 ls コマンドは通常、現在の作業ディレクトリにあるすべてのファイルとディレクトリの名前を一覧表示します。 -l スイッチを使用すると、 ls の動作が変更され、ファイル名だけでなく、各ファイルのサイズ、権限、所有者、変更時刻も表示されます。
スイッチはコマンドごとに異なり、通常はコマンドのマニュアルページに記載されています。ただし、ほとんどのコマンドに共通するスイッチもいくつかあります。たとえば、 --help は通常ヘルプテキストを表示し、 --version は通常コマンドのバージョンを表示し、 -i はアクションを実行する前に対話型プロンプトをオンにすることがよくあります。コマンドのスイッチに関する情報を取得するには、 man your-command-here を試してください。
fishの基本的な考え方は他のUnixシェルと同じです。コマンドラインを取得し、 展開(expansions) を実行し、その結果をコマンドとして実行します。
用語¶
ここではこのページとfishに関するドキュメント全体で使用されている用語の一部を定義します。
引数: コマンドに与えられるパラメータ。
echo fooでは、「foo」が引数となる。組み込みコマンド: シェルによって実装されるコマンド。組み込みコマンドはシェルの動作と密接に結びついているため、外部コマンドとして実装することはできません。
echo fooでは、「echo」は組み込みコマンドです。コマンド: シェルが実行できるプログラム、より正確にはシェルが別のプロセスで実行する外部プログラム。外部コマンドは実行ファイルとしてシステムに提供されます。
echo fooの「echo」は組み込みコマンドであり、command echo fooの「echo」は /bin/echo のようなファイルによって提供される外部コマンドです。関数: 単一のコマンドのように呼び出せるコマンドのブロック。関数を使用することで、複数の単純なコマンドを1つの高度なコマンドにまとめることができます。
ジョブ: 実行中のパイプラインまたはコマンド
パイプライン: 1つのコマンドの出力が次のコマンドの入力になるように連結されたコマンドのセット。
echo foo | grep fooはパイプラインです。リダイレクト: ジョブに関連付けられた入力ストリームまたは出力ストリームのいずれかを変更する操作
スイッチ、オプション: コマンドの動作を変更する特殊な引数。スイッチはほとんどの場合、1つまたは2つのハイフンで始まります。
echo -n fooでは「-n」はオプションです。
クォート¶
スペースや $ 、 * など、fish特有の文字を含む引数をコマンドに与えたい場合があります。その場合は引用符を使用します:
rm "my file.txt"
my と file.txt という2つのファイルを削除しようとする代わりに、 my file.txt というファイルを削除します。
Fishは2種類の引用符(')と二重引用符(")を理解しますが、動作が少し異なります。
一重引用符で囲まれた部分では、fishは展開を行いません。二重引用符で囲まれた部分では、fishは 変数展開 と $(command) 内の コマンド置換 のみを行います。その他の展開(括弧展開 やパラメータ展開を含む)は行わず、エスケープシーケンス(例: \n)は無視されます。引用符内では、引数の区切りに空白は使用されないため、引用符で囲まれた引数にはスペースを含めることができます。
一重引用符内で有効なエスケープシーケンスは、一重引用符をエスケープする \' と、バックスラッシュ記号をエスケープする \\ のみです。二重引用符内で有効なエスケープシーケンスは、二重引用符をエスケープする \" 、ドル記号をエスケープする \$ 、バックスラッシュと改行を削除する \ の後に続く改行、およびバックスラッシュ記号をエスケープする \\ のみです。
一重引用符は二重引用符内では特別な意味を持ちません。逆もまた同様です。
その他の例:
grep 'enabled)$' foo.txt
foo.txt で enabled) で終わる行を検索します($ は grep にとって特別なもので、行末と一致します)
apt install "postgres-*"
現在のディレクトリで「postgres-」から始まるファイルを探す代わりに、「postgres-」で始まる名前を持つすべてのパッケージをインストールします。
文字のエスケープ¶
一部の文字はコマンドラインに直接記述できません。これらの文字には、いわゆるエスケープシーケンスが用意されています。これらは:
\a警告文字\eエスケープ文字\fフィード文字\n改行文字\r復帰文字\tタブ文字\垂直タブ文字\xHH、\XHH(HHは16進数)は、指定された値を持つ1バイトのデータを表します。例えば、\x9はタブ文字です。マルチバイトエンコーディングを使用している場合、これは無効な文字列を入力するために使用できます。通常、fishはASCIIまたはUTF-8エンコードで実行されるため、\X7fまではASCII文字となります。\ooo(oooは8進数)は、指定された値を持つASCII文字を表します。例えば、\011はタブ文字です。許容される最大値は\177です。\uXXXX(XXXXは16進数)は、指定された値を持つ16ビットUnicode文字を表します。例えば、\u9はタブ文字です。\UXXXXXXXX(XXXXXXXXは16進数)は、指定された値を持つ32ビットUnicode文字を表します。例えば、\U9はタブ文字です。許容される最大値は\U10FFFFです。\cX(Xはアルファベットの文字)は、コントロールキーと指定された文字を押すことで生成される制御シーケンスを表します。例えば、\ciはタブ文字です。
一部の文字はシェルにとって特別な意味を持ちます。例えば、アポストロフィ ' は展開を無効にします( クォート 参照)。シェルにこれらの文字を文字通りに扱うように指示するには、バックスラッシュでエスケープします。例えば、以下のコマンドは:
echo \'hello world\'
'hello world' (アポストロフィを含む)を出力しますが、次のコマンド:
echo 'hello world'
hello world (アポストロフィなし)を出力します。前者の場合、シェルはアポストロフィを文字通りの ' 文字として扱いますが、後者の場合、シェルはそれらを特別な展開修飾子として扱います。
特殊文字とそのエスケープシーケンス:
\(バックスラッシュ スペース) はスペース文字をエスケープします。これにより、シェルはエスケープされたスペースで引数を分割しなくなります。\$ダラーをエスケープ\\バックスラッシュをエスケープ\*アスタリスクをエスケープ\?クエスチョンをエスケープ (qmark-noglob機能フラグ が有効になっている場合は必要ありません)\~チルダをエスケープ\#ハッシュをエスケープ\(左括弧をエスケープ\)右括弧をエスケープ\{左中括弧をエスケープ\}右中括弧をエスケープ\[左大括弧をエスケープ\]右大括弧をエスケープ\<小なり記号をエスケープ\>大なり記号をエスケープ\&アンパサンドをエスケープ\|垂直バーをエスケープ\;セミコロンをエスケープ\"二重引用符をエスケープ\'アポストロフィをエスケープ
特別なケースとして、 \ の直後にリテラルな改行が続く場合は「継続」となり、fishに改行を無視して次の行の先頭から入力を再開するように指示します(空白を挿入したりトークンを終了したりしません)。
入力/出力 リダイレクション¶
ほとんどのプログラムは3つの入出力(I/O)ストリームを使用します。
標準入力(stdin)は読み込みます。デフォルトではキーボードから読み込みます。
標準出力(stdout)は書き出します。デフォルトでは画面に出力します。
標準エラー出力(stderr)はエラーとワーニングを書き出します。デフォルトでは画面に出力します。
各ストリームにはファイルディスクリプタ(FD)と呼ばれる番号があります。0はstdin、1はstdout、2はstderrです。
ストリームの出力先は、リダイレクトと呼ばれるものを使って変更できます。例えば、 echo hello > output.txt は、 echo コマンドの標準出力をテキストファイルにリダイレクトします。
<SOURCE_FILEは標準入力からファイルを読み込みます。<?SOURCE_FILEは標準入力からファイルを、読み込めない場合は /dev/null から読み込みます。(訳Note: 読み込めない場合の挙動が変わります。<の場合にはエラーとなり。<?の場合にはエラーとなりません。)>DESTINATIONは標準出力をファイルに書き込みます。2>DESTINATIONは標準エラー出力をファイルに書き込みます。 [1]>>DESTINATION_FILE標準出力をファイルに追加します。2>>DESTINATION_FILE標準エラー出力をファイルに追加します。既存のファイルを上書き(「clobber」)しないようにするには、
>?DESTINATIONと2>?DESTINATION使用します。(訳Note: 書き込み対象ファイルが存在する場合にはエラーとなります。)
DESTINATION(宛先) は次のいずれかになります:
出力を書き込むファイル名。出力を「sinkhole」ファイルに書き込むことで無音にするため、通常は``>/dev/null`` を使用します。
アンパサンド(
&)に続けて別のファイルディスクリプタ番号(標準エラーの場合は&2など)を指定します。出力は宛先記述子に書き込まれます。アンパサンドに続いてマイナス記号(
&-)です。ファイルディスクリプタは閉じられます。Note: これにより、書き込みが失敗し、プログラムが失敗する可能性があります。
リダイレクト &> を使用してstdoutとstderrの両方を同じ宛先に向けることができます。たとえば、 echo hello &> all_output.txt は、stdout と stderr の両方をファイル``all_output.txt`` にリダイレクトします。これは echo hello > all_output.txt 2>&1 と同等です。&>> を使用してstdoutとstderrの両方を同じ出力先に追記することもできます。
リダイレクトの前にFD番号を付けることで、任意のファイルディスクリプタをリダイレクトで使用できます。
N<DESTINATIONディスクリプタ Nの入力をリダイレクトする。N>DESTINATIONディスクリプタ Nの出力をリダイレクトする。N>>DESTINATIONディスクリプタ Nの出力をファイルに追記する。
<? はファイルディスクリプタ(FD)を受け付けません。 < を使用してください。
例:
# Write `foo`'s standard error (file descriptor 2)
# to a file called "output.stderr":
foo 2> output.stderr
# if $num doesn't contain a number,
# this test will be false and print an error,
# so by ignoring the error we can be sure that we're dealing
# with a number in the "if" block:
if test "$num" -gt 2 2>/dev/null
# do things with $num as a number greater than 2
else
# do things if $num is <= 2 or not a number
end
# Save `make`s output in a file:
make &>/log
# Redirections stack and can be used with blocks:
begin
echo stdout
echo stderr >&2 # <- this goes to stderr!
end >/dev/null # ignore stdout, so this prints "stderr"
# print all lines that include "foo" from myfile, or nothing if it doesn't exist.
string match '*foo*' <?myfile
組み込み関数、関数、またはブロックを複数のファイルディスクリプタにリダイレクトすることはできません。ただし、これは外部コマンドではサポートされています。
Piping¶
Another way to redirect streams is a pipe. A pipe connects streams with each other. Usually the standard output of one command is connected with the standard input of another. This is done by separating commands with the pipe character |. For example:
cat foo.txt | head
The command cat foo.txt sends the contents of foo.txt to stdout. This output is provided as input for the head program, which prints the first 10 lines of its input.
It is possible to pipe a different output file descriptor by prepending its FD number and the output redirect symbol to the pipe. For example:
make fish 2>| less
will attempt to build fish, and any errors will be shown using the less pager. [2]
As a convenience, the pipe &| (as well as the |& alias which is also supported by Bash) both redirect stdout and stderr to the same process.
A "pager" here is a program that takes output and "paginates" it. less doesn't just do pages, it allows arbitrary scrolling (even back!).
Combining pipes and redirections¶
It is possible to use multiple redirections and a pipe at the same time. In that case, they are read in this order:
First the pipe is set up.
Then the redirections are evaluated from left-to-right.
This is important when any redirections reference other file descriptors with the &N syntax. When you say >&2, that will redirect stdout to where stderr is pointing to at that time.
Consider this helper function:
# Make a function that prints something to stdout and stderr
function print
echo out
echo err >&2
end
Now let's see a few cases:
# Redirect both stderr and stdout to less
print 2>&1 | less
# or
print &| less
# Show the "out" on stderr, silence the "err"
print >&2 2>/dev/null
# Silence both
print >/dev/null 2>&1
Job control¶
When you start a job in fish, fish itself will pause, and give control of the terminal to the program it just started. Sometimes, you want to continue using the commandline, and have the job run in the background. To create a background job, append an & (ampersand) to your command. This will tell fish to run the job in the background. Background jobs are very useful when running programs that have a graphical user interface.
例:
emacs &
will start the emacs text editor in the background. fg can be used to bring it into the foreground again when needed.
Most programs allow you to suspend the program's execution and return control to fish by pressing ctrl-z (also referred to as ^Z). Once back at the fish commandline, you can start other programs and do anything you want. If you then want you can go back to the suspended command by using the fg (foreground) command.
If you instead want to put a suspended job into the background, use the bg command.
To get a listing of all currently started jobs, use the jobs command. These listed jobs can be removed with the disown command.
At the moment, functions cannot be started in the background. Functions that are stopped and then restarted in the background using the bg command will not execute correctly.
If the & character is followed by a non-separating character, it is not interpreted as background operator. Separating characters are whitespace and the characters ;<>&|.
関数(ファンクション)¶
関数はfish構文で書かれたプログラムです。関数は、様々なコマンドとその引数を一つの名前でまとめます。
例えば、ディレクトリを一覧表示する簡単な関数は次のようになります:
function ll
ls -l $argv
end
最初の行は、コマンドラインで ll と入力することで使用できるように、 ll という名前で関数を定義するように指示しています。2行目は、 ll が呼び出されたときに ls l $argv コマンドを実行するように指示しています。 $argv は list variable であり、関数に渡されるすべての引数を常に含みます。上記の例では、これらはlsコマンドに渡されます。3行目のendで定義は終了します。
これを ll /tmp/ として呼び出すと、 ls l /tmp/ が実行され、 /tmp の内容を一覧表示します。
これは alias と呼ばれる関数の一種です。
Fishのプロンプトは fish_prompt という関数で定義されています。これはプロンプトが表示される直前に実行され、その出力がプロンプトを形成します:
function fish_prompt
# A simple prompt. Displays the current directory
# (which fish stores in the $PWD variable)
# and then a user symbol - a '►' for a normal user and a '#' for root.
set -l user_char '►'
if fish_is_root_user
set user_char '#'
end
echo (set_color yellow)$PWD (set_color purple)$user_char
end
関数を編集するには funced を使用し、関数を保存するには funcsave を使用します。これにより関数はファンクションファイルに保存され、fishは必要に応じて自動的に読み込みます。(autoload)
functions は現在の関数定義を表示します(関数が与えられた場合、type も同様に機能します)。
関数の詳細については、組み込み 関数 のドキュメントを参照してください。
エイリアス定義¶
関数の最も一般的な用途は、既存のコマンドの動作をわずかに変更することです。例えば、 ls コマンドをカラー表示に再定義したいとします。GNUシステムではカラー表示を有効にするスイッチは --color=auto です。lsのエイリアスは次のようになります:
function ls
command ls --color=auto $argv
end
エイリアスについて注意すべき重要な点がいくつかあります:
ラップされたコマンドのパラメータリストに必ず $argv 変数を追加してください。これにより、ユーザーが関数に追加のパラメータを指定した場合、それらのパラメータが基になるコマンドに渡されるようになります。
エイリアスがコマンドと同じ名前の場合、関数が自分自身を呼び出すのではなく、同じ名前のコマンドを呼び出すように指示するために、プログラムの呼び出しの前に
commandを付ける必要があります。これを忘れると、関数は自分自身を呼び出し続けます。通常、fishはこれを理解し、呼び出しを控えます。
この形式の関数を簡単に作成するには、 alias コマンドを使用します。他のシェルとは異なり、fishには「alias」という概念がないため、関数を単純にラップするだけです。alias は即座に関数を作成します。毎回aliasを再作成するのではなく、 alias --save 、 funcsave を使用して、作成された関数をオートロードファイルに保存してください。
代替案として、 略語 を試してみてください。略語とは、シェル内で関数としてではなく、入力中に展開される単語です。
関数のオートロード¶
関数はコマンドラインまたは設定ファイルで定義できますが、自動的にロードすることもできます。これにはいくつかの利点があります。
オートロードされた関数は、実行中のすべてのシェルで自動的に利用可能になります。
関数定義が変更され、しばらくすると実行中のすべてのシェルが自動的に変更されたバージョンを再読み込みします。
その他、起動時間やメモリ使用量が改善されます。
fishが関数をロードする必要がある場合、 list variable の $fish_function_path 内ディレクトリを検索し、関数名に接尾辞 .fish が付いた名前のファイルを探し、最初に見つかったものをロードします。
例えば、 banana という名称の関数を実行しようとすると、fishは $fish_function_path 内のすべてのディレクトリを調べて banana.fish という名称のファイルを探し、最初に見つかったものをロードします。
デフォルトでは $fish_function_path には以下が含まれます:
ユーザーが独自の関数を保存するためのディレクトリ。通常は
~/.config/fish/functions(XDG_CONFIG_HOME環境変数によって制御されます)システム上のすべてのユーザーの関数のディレクトリ。通常は
/etc/fish/functions(実際は$__fish_sysconfdir/functions)他のソフトウェアが独自の関数を配置するためのディレクトリ。これらは、
$__fish_user_data_dir(通常は~/.local/share/fish、XDG_DATA_HOME環境変数によって制御されます)の下のディレクトリと、XDG_DATA_DIRS環境変数のfish/vendor_functions.dというサブディレクトリにあります。XDG_DATA_DIRSのデフォルト値は通常、/usr/share/fish/vendor_functions.dと/usr/local/share/fish/vendor_functions.dです。
よくわからない場合、関数はおそらく ~/.config/fish/functions にあるはずです。
説明したように、オートロードファイルは名前でロードされるため、1つのファイルに複数の関数を入れることはできますが、同じ名前を持つ関数を実行しようとしたときにのみ、ファイルが自動的にロードされます。
オートロードは イベントハンドラ では機能しません。これは、関数がまだロードされていない場合、イベントが発生したときに関数が実行されるべきかどうかをfishが認識できないためです。詳細については、 イベントハンドラ のセクションを参照してください。
ファイルと関数を同じ名称で定義していない場合、fishは他の自動ロードファイルを読み込まず、代わりに組み込みコマンドを試し、最終的にコマンドを実行します。これにより、 $fish_function_path 内に後から定義した関数でマスクできます。たとえば、管理者が /etc/fish/functions に入れた関数をスキップしたい場合などです。
別のプログラムを開発していて、そこにfish関数をインストールしたい場合は、「ベンダー」関数ディレクトリにインストールします。このパスはシステムによって異なるため、 pkgconfig を使用し pkg-config --variable functionsdir fish の出力から検出します。他のディストリビュータが簡単に変更可能とするため、インストールシステムはpkgconfigパスを上書きするためのカスタムパスをサポートする必要があります。
条件¶
Fishには、特定の条件が満たされた場合にのみコマンドを実行できる組み込み関数がいくつかあります。if, switch, and and or そして &&/|| 構文です。
if 構文¶
if 構文は条件が真であればコマンドブロックを実行します
他のシェルと同様ですが、一般的なプログラミング言語とは異なり、ここでの条件は コマンド です。Fishはそれを実行し、真の 終了ステータス (つまり0)を返した場合、ifブロックが実行されます。例えば:
if test -e /etc/os-release
cat /etc/os-release
end
これは test コマンドを使って /etc/os-release ファイルが存在するかどうかを確認します。存在する場合はcatコマンドを実行し、画面に出力します。
他のシェルとは異なり、条件コマンドは最初のジョブの後に終了し、 then は存在しません。 and や or のような結合子は条件を拡張します。
A more complicated example with a command substitution:
if test "$(uname)" = Linux
echo I like penguins
end
test はさまざまな判定に使用できるため、変数とコマンド置換を引用符で囲むことが重要です。$(uname) が引用符で囲まれておらず、 uname が何も出力しない場合は、 test = Linux が実行され、エラーが発生します。
if は、追加の条件を持つ else if 節と、他のすべてが偽であった場合に実行される else 節を取ることもできます:
if test "$number" -gt 10
echo Your number was greater than 10
else if test "$number" -gt 5
echo Your number was greater than 5
else if test "$number" -gt 1
echo Your number was greater than 1
else
echo Your number was smaller or equal to 1
end
not はステータスを反転するために使用できます:
# Check if the file contains the string "fish" anywhere.
# This executes the `grep` command, which searches for a string,
# and if it finds it returns a status of 0.
# The `not` then turns 0 into 1 or anything else into 0.
# The `-q` switch stops it from printing any matches.
if not grep -q fish myanimals
echo "You don't have fish!"
else
echo "You have fish!"
end
if条件でよく使われるその他のもの
switch 構文¶
switch コマンドは、文字列の値に応じて、複数のコマンドブロックのいずれかを実行するために使用されます。文字列が一致した場合に実行される case ブロックを複数指定できます。caseブロックには wildcards を使用できます。例えば:
switch (uname)
case Linux
echo Hi Tux!
case Darwin
echo Hi Hexley!
case DragonFly '*BSD'
echo Hi Beastie! # this also works for FreeBSD and NetBSD
case '*'
echo Hi, stranger!
end
他のシェルやプログラミング言語とは異なり、フォールスルーはなく、最初に一致する case ブロックが実行され、その後制御が switch ブロックが終了します。
結合演算子 (and / or / && / ||)¶
単純なチェックには結合演算子を使うことができます。and 、 && は最初のコマンドが成功した場合に2番目のコマンドを実行。or は最初のコマンドが失敗した場合に2番目のコマンドを実行します。例えば:
# $XDG_CONFIG_HOME is a standard place to store configuration.
# If it's not set applications should use ~/.config.
set -q XDG_CONFIG_HOME; and set -l configdir $XDG_CONFIG_HOME
or set -l configdir ~/.config
結合演算子は 遅延評価 されます。最終的なステータスを決定するために必要な部分のみ実行されることに注意してください。
比較:
if sleep 2; and false
echo 'How did I get here? This should be impossible'
end
と:
if false; and sleep 2
echo 'How did I get here? This should be impossible'
end
これらは本質的に同じことを行いますが、前者は sleep を常に実行する必要があるため、2秒長くかかります。
あるいは、早期に停止する必要がある場合もあります:
if command -sq foo; and foo
コマンド「foo」が存在しないことを確認した後にこれを実行した場合、 foo を実行しようとすると、見つからないためエラーが発生します。
結合演算子は段階的に実行され、望ましくない結果をもたらす可能性があります。長いチェーンを構築することは推奨されません:
test -e /etc/my.config
or echo "OH NO WE NEED A CONFIG FILE"
and return 1
これは、テストが成功した場合も return 1 を実行します。これは、fish が test -e /etc/my.config を実行し、$status を 0 に設定した後、 echo をスキップして $status を 0 のままにし、$status がまだ 0 であるため return 1 を実行するためです。
より複雑な条件や、何かが失敗した後に複数の処理を実行したい場合は、 if 文の使用を検討してください:
if not test -e /etc/my.config
echo "OH NO WE NEED A CONFIG FILE"
return 1
end
ループとブロック¶
ほとんどのプログラミング言語と同様に、fishにもおなじみの while ループと for ループがあります。
while は繰り返しの if のように動作します。:
while true
echo Still running
sleep 1
end
1秒ごとに「Still running」と表示されます。ctrl + cで中止できます。
for ループは他のシェルと同じように動作します。これはC言語のforループよりもPythonのforループに似ています。
for file in *
echo file: $file
end
現在のディレクトリにある各ファイルを表示します。 in の後の部分は引数のリストなので、任意の 展開(expansions) を使用できます。
set moreanimals bird fox
for animal in {cat,}fish dog $moreanimals
echo I like the $animal
end
数字のリストが必要な場合は、 seq コマンドを使用して作成できます。
for i in (seq 1 5)
echo $i
end
break はループから抜け出し、 continue は次の反復にジャンプするために使用できます。
入力と出力のリダイレクト (パイプ 含む)はループにも適用できます:
while read -l line
echo line: $line
end < file
さらに、コマンドをグループ化する begin ブロックがあるので、ブロックにリダイレクトしたり、繰り返しなしで新しい variable scope スコープを使用したりできます:
begin
set -l foo bar # this variable will only be available in this block!
end
パラメータ展開¶
fishはコマンドラインを受け取ると、コマンドに渡す前にパラメータを展開します。展開には、以下のような複数の異なる種類があります。
ワイルドカード: パターンからファイル名を作成します -
*.jpg変数展開: 変数の値を使用します -
$HOMEコマンド置換: 他のコマンドの出力を利用します -
$(cat /path/to/file)ブレース展開: 共通の接頭辞や接尾辞を持つリストを短く記述します
{/usr,}/binチルダ展開: パスの先頭にある ~ をホームディレクトリへのパスに変換します
~/bin
パラメータ展開は524,288個までに制限されています。オペレーティングシステムがコマンドに許可する引数の数には制限があり、524,288はその制限を大きく上回っています。これは、シェルが無益な計算によってハングアップするのを防ぐための措置です。
ワイルドカード(グロビング)¶
パラメータに 引用符で囲まれていない * (アスタリスク)または ? (疑問符)が含まれている場合、fishはそれらをファイルにマッチさせるためのワイルドカードとして使用します。
*は、ファイル名に含まれる(0文字以上の)任意の数の文字にマッチします。これに/は含まれません。**は(0文字以上の)任意の数の文字にマッチし、サブディレクトリ内も再帰的に検索します。**が単独のセグメントである場合、他のシェルとの互換性のために、そのセグメントは0回(マッチなし)とみなされる場合があります。?は/を除く任意の1文字にマッチします。これは非推奨となっており、qmark-noglob機能フラグ を通じて無効化できます。無効化された場合、?は通常の文字として扱われます。
ワイルドカードによる一致結果は、大文字と小文字を区別せずにソートされます。数値を含む結果をソートする場合、'1'、'5'、'12' のような文字列が 1、5、12 の順になるよう、自然順でソートされます。
隠しファイル(名前がドットで始まるもの)は、ワイルドカード文字列のその場所にドットがない限り、マッチングの対象になりません。
例:
a*は、カレントディレクトリ内にある 'a' で始まるすべてのファイルにマッチします。**は、カレントディレクトリおよびそのすべてのサブディレクトリ内にあるすべてのファイルとディレクトリにマッチします。~/.*は、ホームディレクトリ内にあるすべての隠しファイル(「ドットファイル」とも呼ばれます)とディレクトリにマッチします。
ほとんどのコマンドにおいて、ワイルドカードの展開に一つでも失敗すると、そのコマンドは実行されず、$status に非ゼロの値が設定され、警告が表示されます。この挙動は、bashで shopt -s failglob を設定した場合と同様です。ただし例外もあり、具体的には set、path、変数の一時的な上書き、count、および for が該当します。これらのコマンドでは、グロブは(コマンド側からは何も見えないように)0個の引数に展開されます。これはbashで shopt -s nullglob を設定した場合と同様です。
例:
# List the .foo files, or warns if there aren't any.
ls *.foo
# List the .foo files, if any.
set foos *.foo
if count $foos >/dev/null
ls $foos
end
(デフォルトの)bashとは異なり、fishは一致するものが見つからなかった場合にグロブ文字をそのまま渡しません。そのため、apt install のようにコマンド側でマッチングを行う場合は、以下のように引用符を追加する必要があります。
apt install "ncurses-*"
変数展開¶
fishにおける最も重要な展開の一つが「変数展開」です。これは、ドル記号($)に続く変数名を、その変数の「値」に置き換える処理です。
簡単な例:
echo $HOME
これは $HOME を現在のユーザーのホームディレクトリに置き換え、それを echo に渡して表示します。
$HOME のような一部の変数は、fishがデフォルトで設定しているか、fishの親プロセスが起動時に渡しているため、あらかじめ設定されています。独自の変数は set を使って定義できます。
set my_directory /home/cooluser/mystuff
ls $my_directory
# shows the contents of /home/cooluser/mystuff
変数設定の仕組みの詳細については、シェル変数 とそれに続くセクションを参照してください。
変数が未定義または空であるために値を持たず、「無」として展開されることもあります:
echo $nonexistentvariable
# Prints no output.
変数名とテキストを区別するために、変数を二重引用符(ダブルクォート)または中括弧(ブレース)で囲むことができます:
set WORD cat
echo The plural of $WORD is "$WORD"s
# Prints "The plural of cat is cats" because $WORD is set to "cat".
echo The plural of $WORD is {$WORD}s
# ditto
引用符や中括弧がない場合、fishは存在しない可能性のある $WORDs という名前の変数を展開しようとします。
後者の {$WORD} という構文は、 ブレース展開 の特殊なケースです。
ここで $WORD が未定義または空のリストである場合、 "s" は表示されません。しかし、$WORD が空の文字列である場合(set WORD "" の後など)は、"s" は表示されます。
シェル変数の詳細については、 シェル変数 セクションを参照してください。
変数のクォーティング¶
変数展開は二重引用符で囲まれた文字列内でも行われます。二重引用符("これ")の中では、変数は常に正確に1つの引数として展開されます。変数が空または未定義の場合は、空の文字列になります。要素が1つの場合は、その要素に展開されます。要素が複数ある場合は、各要素がスペースで結合されます。ただし、その変数が パス変数 である場合は、代わりにコロン(:)で結合されます [3]。
fishの変数はすべて リスト であり、これらは「設定」(set)された時に要素へと分割されます。つまり、 set を使用する際に引用符を使うか使わないかを決めることが重要になります:
set foo 1 2 3 # a variable with three elements
rm $foo # runs the equivalent of `rm 1 2 3` - trying to delete three files: 1, 2 and 3.
rm "$foo" # runs `rm '1 2 3'` - trying to delete one file called '1 2 3'
set foo # an empty variable
rm $foo # runs `rm` without arguments
rm "$foo" # runs the equivalent of `rm ''`
set foo "1 2 3"
rm $foo # runs the equivalent of `rm '1 2 3'` - trying to delete one file
rm "$foo" # same thing
これは他のシェルとは異なります。他のシェルでは「ワードスプリッティング(単語の分割)」として知られる処理が行われ、変数が展開に 使用 される時に分割されます。例えばbashでは以下のようになります:
foo="1 2 3"
rm $foo # runs the equivalent of `rm 1 2 3`
rm "$foo" # runs the equivalent of `rm '1 2 3'`
これは、bashスクリプトにおいてスペースを含むファイル名で非常によく発生する問題の原因となっています。
fishでは、引用符で囲まれていない変数はその要素の数だけ引数として展開されます。つまり、空のリストは「無」に展開され、1つの要素を持つ変数はその要素に展開され、複数の要素を持つ変数はそれぞれの要素に個別に展開されます。
変数が「無」として展開される場合、その変数に付随する他の文字列も取り消されます。詳細については、 リストの結合 セクションを参照してください。
ほとんどの場合、変数に引用符を付けないのが正解です。例外は、変数が未設定であったり複数の要素を持っていたりする場合でも、必ず1つの要素として渡す必要がある場合です。これは test でよく発生します:
set -l foo one two three
test -n $foo
# prints an error that it got too many arguments, because it was executed like
test -n one two three
test -n "$foo"
# works, because it was executed like
test -n "one two three"
(通常はスペースである)$IFS の最初の文字で結合するbashやzshとは異なります。
変数のデリファレンス(逆参照)¶
$ 記号を複数回使用することで、(C言語やC++の * のような)一種の「デリファレンス」演算子として扱うことができます。以下のコードのようになります。
set foo a b c
set a 10; set b 20; set c 30
for i in (seq (count $$foo))
echo $$foo[$i]
end
# Output is:
# 10
# 20
# 30
$$foo[$i] は、「 $foo[$i] という名前を持つ変数の値」を意味します。
これは、関数に変数の名前を渡すためにも使用できます。
function print_var
for arg in $argv
echo Variable $arg is $$arg
end
end
set -g foo 1 2 3
set -g bar a b c
print_var foo bar
# prints "Variable foo is 1 2 3" and "Variable bar is a b c"
当然ながら、その変数は関数からアクセス可能である必要があるため、 グローバルまたはユニバーサル であるか、 エクスポート されている必要があります。また、関数内部で使用されている変数名と衝突してはいけません。したがって、もし $foo をローカル変数にしていたり、あるいは名前を "arg" にしていたりすると、正しく動作しません。
この機能を スライス と組み合わせて使用する場合、スライスは内側から外側に向かって適用されます。 $$foo[5] は、 $foo が参照するすべての変数の5番目の要素を返すのではなく、 $foo の5番目の要素を変数名として使用します。前者の挙動をさせたい場合は、 $$foo[1..-1][5] ( $foo のすべての要素を取得し、それらを変数名として使用した上で、それらの5番目の要素を返す)と記述します。
さらなる例:
set listone 1 2 3
set listtwo 4 5 6
set var listone listtwo
echo $$var
# Output is 1 2 3 4 5 6
echo $$var[1]
# Output is 1 2 3
echo $$var[2][3]
# $var[2] is listtwo, third element of that is 6, output is 6
echo $$var[..][2]
# The second element of every variable, so output is 2 5
コマンドとしての変数¶
他のシェルと同様に、変数の値をコマンドとして実行できます。
> set -g EDITOR emacs
> $EDITOR foo # opens emacs, possibly the GUI version
If you want to give the command an argument inside the variable it needs to be a separate element:
> set EDITOR emacs -nw
> $EDITOR foo # opens emacs in the terminal even if the GUI is installed
> set EDITOR "emacs -nw"
> $EDITOR foo # tries to find a command called "emacs -nw"
また、他のシェルと同様に、これが機能するのは外部コマンド、組み込みコマンド、関数のみです。キーワードについては、構文上の重要な意味を持つため機能しません。
例えば、set if $if とした後に $if を使っても ifブロックを作成することはできません。同様に set cmd command としても、 command デコレータとして使用することはできず、 $cmd -q foo のような(外部コマンドとしての)利用に限られます。
コマンド置換¶
「コマンド置換」とは、あるコマンドの「出力」を別のコマンドの引数として利用する展開機能のことです。例えば以下のようになります:
echo $(pwd)
これは pwd コマンドを実行し、その出力(より具体的には標準出力「stdout」ストリームに書き込まれた内容)をキャプチャして、 echo の引数として使用します。そのため、内側のコマンド(pwd)が先に実行され、それが完了してから外側のコマンドが開始されます。
内側のコマンドが複数行を出力する場合、fishは各行を個別の引数として外側のコマンドに渡します。他のシェルとは異なり、 $IFS の値は使用されず [4]、fishは改行で分割を行います。
コマンド置換を二重引用符で囲むこともできます:
echo "$(pwd)"
二重引用符を使用する場合、コマンド出力は行ごとに分割されませんが、末尾の空行は削除されます。
出力が最後のステップとして string split 、 string split0 にパイプで渡された場合、行分割の代わりとして、それらによる分割結果がそのまま使用されます。
fishでは、 echo (pwd) のようにドル記号なしでコマンド置換を記述することも可能です。この形式は二重引用符内では展開されません(echo "(pwd)" は (pwd) と表示されます)。
置換が set コマンドのコンテキスト内で行われた場合、最後に実行されたコマンド置換の終了ステータスを status 変数で利用できます(例: if set -l (something) は something が真を返したかどうかを判定します)。
出力の特定の行のみを使用するには、 スライス を参照してください。
例:
# Outputs 'image.png'.
echo (basename image.jpg .jpg).png
# Convert all JPEG files in the current directory to the
# PNG format using the 'convert' program.
for i in *.jpg; convert $i (basename $i .jpg).png; end
# Set the ``data`` variable to the contents of 'data.txt'
# without splitting it into a list.
set data "$(cat data.txt)"
# Set ``$data`` to the contents of data, splitting on NUL-bytes.
set data (cat data | string split0)
あるコマンドの出力を、ファイルのみを受け付ける別のコマンドに渡したい場合があります。対象が1つのファイルだけであれば、通常は以下のようにパイプ経由で渡すことができます:
grep fish myanimallist1 | wc -l
しかし、複数の出力を渡す必要がある場合や、コマンドが標準入力から読み込まない場合は、「プロセス展開」が便利です。他のシェルでは foo <(bar) <(baz) のような構文が使われますが、fishでは psub コマンドを使用します:
# Compare only the lines containing "fish" in two files:
diff -u (grep fish myanimallist1 | psub) (grep fish myanimallist2 | psub)
これは一時ファイルを作成し、コマンドの出力をそのファイルに保存してファイル名を出力します。これにより、外側のコマンドにそのファイル名が渡されます。
fishには、コマンド置換で読み込むデータ量に対してデフォルトで1GiBの制限があります。この制限に達すると、コマンド(コマンド置換だけでなく、外側のコマンドも一切実行されません)は失敗し、 $status に122が設定されます。これは、コマンド置換によってシステムがメモリ不足に陥るのを防ぐためのものです。通常、オペレーティングシステムの制限はこれよりもはるかに低いため、それ以上のデータを読み込むことは無益で有害です。この制限は fish_read_limit 変数で調整可能です(0 は無制限を意味します)。この制限は read コマンドにも影響します。
例外が1つあります。 $IFS を空に設定すると、行分割が無効になります。これは非推奨ですので、代わりに string split を使用してください。
ブレース展開¶
波括弧(中括弧)を使用して、カンマ区切りのリストを記述できます。これらは展開され、各要素が周囲の文字列を付加した新しいパラメータとなります。これはタイピングの手間を省いたり、変数名と周囲のテキストを区別したりするのに便利です。
例:
> echo input.{c,h,txt}
input.c input.h input.txt
# Move all files with the suffix '.c' or '.h' to the subdirectory src.
> mv *.{c,h} src/
# Make a copy of `file` at `file.bak`.
> cp file{,.bak}
> set -l dogs hot cool cute "good "
> echo {$dogs}dog
hotdog cooldog cutedog good dog
波括弧の中に「,」や変数展開が含まれていない場合、それらは展開されません:
# This {} isn't special
> echo foo-{}
foo-{}
# This passes "HEAD@{2}" to git
> git reset --hard HEAD@{2}
> echo {{a,b}}
{a} {b} # because the inner brace pair is expanded, but the outer isn't.
展開の結果、ブレースの中に何も残らない場合、その引数は削除されます(詳細は リストの結合 セクションを参照してください):
> echo foo-{$undefinedvar}
# Output is an empty line, like a bare `echo`.
ブレースとカンマの間、あるいは2つのカンマの間に何もない場合は、空の要素として解釈されます:
> echo {,,/usr}/bin
/bin /bin /usr/bin
「,」を要素として使用するには、 引用符で囲む か エスケープ してください。
コマンドトークンの最初の文字は、ブレース展開として解釈されることはありません。なぜなら、それは 複合文 の開始を意味するためです:
> {echo hello, && echo world}
hello,
world
Combining lists¶
Fish expands lists like brace expansions:
>_ set -l foo x y z
>_ echo 1$foo
# Any element of $foo is combined with the "1":
1x 1y 1z
>_ echo {good,bad}" apples"
# Any element of the {} is combined with the " apples":
good apples bad apples
# Or we can mix the two:
>_ echo {good,bad}" "$foo
good x bad x good y bad y good z bad z
Any string attached to a list will be concatenated to each element.
Two lists will be expanded in all combinations - every element of the first with every element of the second:
>_ set -l a x y z; set -l b 1 2 3
>_ echo $a$b # same as {x,y,z}{1,2,3}
x1 y1 z1 x2 y2 z2 x3 y3 z3
A result of this is that, if a list has no elements, this combines the string with no elements, which means the entire token is removed!
>_ set -l c # <- this list is empty!
>_ echo {$c}word
# Output is an empty line - the "word" part is gone
This can be quite useful. For example, if you want to go through all the files in all the directories in PATH, use
for file in $PATH/*
Because PATH is a list, this expands to all the files in all the directories in it. And if there are no directories in PATH, the right answer here is to expand to no files.
Sometimes this may be unwanted, especially that tokens can disappear after expansion. In those cases, you should double-quote variables - echo "$c"word.
This also happens after command substitution. To avoid tokens disappearing there, make the inner command return a trailing newline, or double-quote it:
>_ set b 1 2 3
>_ echo (echo x)$b
x1 x2 x3
>_ echo (printf '%s' '')banana
# the printf prints nothing, so this is nothing times "banana",
# which is nothing.
>_ echo (printf '%s\n' '')banana
# the printf prints a newline,
# so the command substitution expands to an empty string,
# so this is `''banana`
banana
>_ echo "$(printf '%s' '')"banana
# quotes mean this is one argument, the banana stays
Slices¶
Sometimes it's necessary to access only some of the elements of a list (all fish variables are lists), or some of the lines a command substitution outputs. Both are possible in fish by writing a set of indices in brackets, like:
# Make $var a list of four elements
set var one two three four
# Print the second:
echo $var[2]
# prints "two"
# or print the first three:
echo $var[1..3]
# prints "one two three"
In index brackets, fish understands ranges written like a..b ('a' and 'b' being indices). They are expanded into a sequence of indices from a to b (so a a+1 a+2 ... b), going up if b is larger and going down if a is larger. Negative indices can also be used - they are taken from the end of the list, so -1 is the last element, and -2 the one before it. If an index doesn't exist the range is clamped to the next possible index.
If a list has 5 elements the indices go from 1 to 5, so a range of 2..16 will only go from element 2 to element 5.
If the end is negative the range always goes up, so 2..-2 will go from element 2 to 4, and 2..-16 won't go anywhere because there is no way to go from the second element to one that doesn't exist, while going up.
If the start is negative the range always goes down, so -2..1 will go from element 4 to 1, and -16..2 won't go anywhere because there is no way to go from an element that doesn't exist to the second element, while going down.
A missing starting index in a range defaults to 1. This is allowed if the range is the first index expression of the sequence. Similarly, a missing ending index, defaulting to -1 is allowed for the last index in the sequence.
Multiple ranges are also possible, separated with a space.
Some examples:
echo (seq 10)[1 2 3]
# Prints: 1 2 3
# Limit the command substitution output
echo (seq 10)[2..5]
# Uses elements from 2 to 5
# Output is: 2 3 4 5
echo (seq 10)[7..]
# Prints: 7 8 9 10
# Use overlapping ranges:
echo (seq 10)[2..5 1..3]
# Takes elements from 2 to 5 and then elements from 1 to 3
# Output is: 2 3 4 5 1 2 3
# Reverse output
echo (seq 10)[-1..1]
# Uses elements from the last output line to
# the first one in reverse direction
# Output is: 10 9 8 7 6 5 4 3 2 1
# The command substitution has only one line,
# so these will result in empty output:
echo (echo one)[2..-1]
echo (echo one)[-3..1]
The same works when setting or expanding variables:
# Reverse path variable
set PATH $PATH[-1..1]
# or
set PATH[-1..1] $PATH
# Use only n last items of the PATH
set n -3
echo $PATH[$n..-1]
Variables can be used as indices for expansion of variables, like so:
set index 2
set letters a b c d
echo $letters[$index] # returns 'b'
However using variables as indices for command substitution is currently not supported, so:
echo (seq 5)[$index] # This won't work
set sequence (seq 5) # It needs to be written on two lines like this.
echo $sequence[$index] # returns '2'
When using indirect variable expansion with multiple $ ($$name), you have to give all indices up to the variable you want to slice:
> set -l list 1 2 3 4 5
> set -l name list
> echo $$name[1]
1 2 3 4 5
> echo $$name[1..-1][1..3] # or $$name[1][1..3], since $name only has one element.
1 2 3
Home directory expansion¶
The ~ (tilde) character at the beginning of a parameter, followed by a username, is expanded into the home directory of the specified user. A lone ~, or a ~ followed by a slash, is expanded into the home directory of the process owner:
ls ~/Music # lists my music directory
echo ~root # prints root's home directory, probably "/root"
Combining different expansions¶
All of the above expansions can be combined. If several expansions result in more than one parameter, all possible combinations are created.
When combining multiple parameter expansions, expansions are performed in the following order:
Command substitutions
Variable expansions
Bracket expansion
Wildcard expansion
Expansions are performed from right to left, nested bracket expansions and command substitutions are performed from the inside and out.
例:
If the current directory contains the files 'foo' and 'bar', the command echo a(ls){1,2,3} will output abar1 abar2 abar3 afoo1 afoo2 afoo3.
Table Of Operators¶
Putting it together, here is a quick reference to fish's operators, all of the special symbols it uses:
Symbol |
Meaning |
Example |
|---|---|---|
|
|
|
|
|
|
|
Redirection, like |
|
|
Pipe, connect two or more commands |
|
|
End of the command, instead of a newline |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
シェル変数¶
変数は、データを保存して受け渡すための手段です。変数はシェル内だけで使用することもできますし、 「 エクスポート 」して、シェルが起動するあらゆる外部コマンドでそのコピーを利用できるようにすることもできます。エクスポートされた変数は「環境変数」と呼ばれます。
変数の値を設定するには、 set コマンドを使用します。変数名を空にすることはできず、使用できるのは英文字、数字、およびアンダースコアのみです。変数名はこれらのどの文字から始めても、どの文字で終わっても構いません。
例:
変数 smurf_color の値を blue に設定するには、 set smurf_color blue というコマンドを使用します。
変数が設定された後は、 変数展開 を通じてシェル内でその変数の値を使用できるようになります。
例:
set smurf_color blue
echo Smurfs are usually $smurf_color
set pants_color red
echo Papa smurf, who is $smurf_color, wears $pants_color pants
このように、 set で変数を設定し、 $ と変数名を使ってその変数を使用します。
変数のスコープ¶
fishのすべての変数にはスコープがあります。例えば、変数はグローバルにすることもできますし、関数やブロックに対してローカルにすることもできます:
# This variable is global, we can use it everywhere.
set --global name Patrick
# This variable is local, it will not be visible in a function we call from here.
set --local place "at the Krusty Krab"
function local
# This can find $name, but not $place
echo Hello this is $name $place
# This variable is local, it will not be available
# outside of this function
set --local instrument mayonnaise
echo My favorite instrument is $instrument
# This creates a local $name, and won't touch the global one
set --local name Spongebob
echo My best friend is $name
end
local
# Will print:
# Hello this is Patrick
# My favorite instrument is mayonnaise
# My best friend is Spongebob
echo $name, I am $place and my instrument is $instrument
# Will print:
# Patrick, I am at the Krusty Krab and my instrument is
fishには4種類の変数スコープがあります。ユニバーサル変数、グローバル変数、関数変数、そしてローカル変数です。
ユニバーサル変数は、1台のコンピュータ上でユーザーが実行しているすべてのfishセッション間で共有されます。これらはディスクに保存され、再起動後も保持されます。
グローバル変数は、現在のfishセッションに固有のものです。
set -eを明示的に実行することで消去できます。関数変数は、現在実行中の関数に固有のものです。現在の関数が終了すると消去(「スコープ外になる」)されます。関数の外側では、これらがスコープ外になることはありません。
ローカル変数は、現在のコマンドブロックに固有のものであり、特定のブロックがスコープ外になると自動的に消去されます。コマンドブロックとは、
for、while、if、function、begin、switchのいずれかのコマンドで始まり、endコマンドで終わる一連のコマンドを指します。ブロックの外側では、これは関数スコープと同じ扱いになります。
変数は、 -U 、 --universal スイッチでユニバーサルに、 -g 、 --global でグローバルに、 -f 、 --function で関数スコープに、そして -l 、 --local で現在のブロックに対してローカルに、それぞれ明示的に設定できます。変数の作成または更新時のスコープ規則は以下の通りです。
スコープが明示的に指定された場合は、そのスコープが使用されます。別のスコープに同名の変数が存在していても、その変数は変更されません。
スコープが指定されていないが同名の変数が存在する場合、最も小さいスコープの変数が修正されます。その際、スコープ自体は変更されません。
スコープが指定されておらず、同名の変数も存在しない場合、関数内であれば関数スコープに、関数が実行されていなければグローバルスコープに変数が作成されます。
同じ名前で異なるスコープを持つ変数が複数存在することがあります。 変数を使用 する際、その名前を持つ最も小さいスコープの変数が使用されます。もしローカル変数が存在する場合、同名のグローバル変数やユニバーサル変数よりも優先して使用されます。
例:
異なるスコープには、いくつかの使い道があります。
通常、関数内部ではローカルスコープを使用すべきです:
function something
set -l file /path/to/my/file
if not test -e "$file"
set file /path/to/my/otherfile
end
end
# or
function something
if test -e /path/to/my/file
set -f file /path/to/my/file
else
set -f file /path/to/my/otherfile
end
end
config.fish内で何かを設定する場合や、関数内で設定したものをそのセッションの残りの間ずっと利用可能にしたい場合は、グローバルスコープが良い選択肢です:
# Don't shorten the working directory in the prompt
set -g fish_prompt_pwd_dir_length 0
# Set my preferred cursor style:
function setcursors
set -g fish_cursor_default block
set -g fish_cursor_insert line
set -g fish_cursor_visual underscore
end
# Set my language
set -gx LANG de_DE.UTF-8
以下は、ローカル変数と関数スコープ変数の比較例です:
function test-scopes
begin
# This is a nice local scope where all variables will die
set -l pirate 'There be treasure in them thar hills'
set -f captain Space, the final frontier
# If no variable of that name was defined, it is function-local.
set gnu "In the beginning there was nothing, which exploded"
end
# This will not output anything, since the pirate was local
echo $pirate
# This will output the good Captain's speech
# since $captain had function-scope.
echo $captain
# This will output Sir Terry's wisdom.
echo $gnu
end
ある関数が別の関数を呼び出す際、ローカル変数は参照できません:
function shiver
set phrase 'Shiver me timbers'
end
function avast
set --local phrase 'Avast, mateys'
# Calling the shiver function here can not
# change any variables in the local scope
# so phrase remains as we set it here.
shiver
echo $phrase
end
avast
# Outputs "Avast, mateys"
迷ったときは、関数スコープの変数を使用してください。変数をどこからでもアクセス可能にする必要があるときはグローバルに、設定を永続的に保存する必要があるときはユニバーサルにします。短いブロック内だけで変数を使用したいときは、ローカルにしてください。
単一コマンドでの変数の一時的な上書き¶
単一のコマンドに対して変数を一時的に上書きしたい場合は、コマンドの前に "var=val" ステートメントを使用できます:
# Call git status on another directory
# (can also be done via `git -C somerepo status`)
GIT_DIR=somerepo git status
他のシェルとは異なり、fishはまず変数を設定してから、その行の他の展開処理を行います。そのため、以下のようになります:
set foo banana
foo=gagaga echo $foo
# prints gagaga, while in other shells it might print "banana"
ブレース展開 を使って、複数の要素を指定することもできます:
# Call bash with a reasonable default path.
PATH={/usr,}/{s,}bin bash
あるいは、 グロブ を使った例です:
# Run vlc on all mp3 files in the current directory
# If no file exists it will still be run with no arguments
mp3s=*.mp3 vlc $mp3s
他のシェルとは異なり、これによってルックアップ(エイリアスなど)が抑制されることは ありません 。変数の上書きを設定した後にコマンドを呼び出すと、設定前と全く同じコマンドが実行されます。
この構文は fish 3.1 以降でサポートされています。
ユニバーサル変数¶
ユニバーサル変数は、そのコンピュータ上のユーザーのすべての fish セッション間で共有される変数です。ユニバーサル変数へのすべての変更は永続的であり、即座に他の fish セッションへ伝搬されます。
ユニバーサル変数 は、 .config/fish/fish_variables ファイルに保存されます。編集内容が上書きされる可能性があるため、このファイルを直接編集しないでください。代わりに、fish スクリプトを通じて、または fish を対話的に使用して変数を編集してください。
config.fish 内でユニバーサル変数に要素を追加(append)しないでください。新しいシェルが起動するたびに変数が長くなってしまうためです。代わりに、コマンドラインで一度だけ設定するようにしてください。
変数のエクスポート¶
fish の変数はエクスポートすることができ、それにより fish が起動するあらゆるコマンドに継承されます。特に、 PAGER や GOPATH のような外部コマンドの設定に使用される変数や、 PATH や LANGUAGE のような一般的なシステム設定を含む変数にはこれが必要です。外部コマンドが変数を参照する必要がある場合、その変数はエクスポートされていなければなりません。エクスポートされた変数は、しばしば「環境変数」とも呼ばれます。
これは fish 自体にも当てはまります。fish は起動時に、親プロセス(通常はターミナル)から環境変数を受け取ります。これらには通常、 PATH や ロケール変数 などのシステム設定が含まれます。
変数は、 -x 、 --export スイッチで明示的にエクスポートするように設定でき、 -u 、 --unexport スイッチでエクスポートしないように設定できます。変数を設定する際のエクスポート規則は、変数のスコーピング規則と似ています。オプションが渡された場合はそれが尊重され、そうでない場合は変数の既存の状態が維持されます。オプションが渡されず、かつ変数がまだ存在していなかった場合、その変数はエクスポートされません。
命名規則として、エクスポートされた変数は大文字で、エクスポートされていない変数は小文字で記述します。
例:
set -gx ANDROID_HOME ~/.android # /opt/android-sdk
set -gx CDPATH . ~ (test -e ~/Videos; and echo ~/Videos)
set -gx EDITOR emacs -nw
set -gx GOPATH ~/dev/go
set -gx GTK2_RC_FILES "$XDG_CONFIG_HOME/gtk-2.0/gtkrc"
set -gx LESSHISTFILE "-"
Note: エクスポートは スコープ ではなく、追加の状態です。通常、エクスポートされた変数はグローバルにもするのが理にかなっていますが、 変数の一時的な上書き よりも詳細な制御が必要な場合には、ローカルでエクスポートされた変数が役立ちます。これらは関数に「コピー」されるため、関数が外部の値を変更することはできませんが、コマンドからは引き続き利用可能です。グローバル変数は、エクスポートされているかどうかにかかわらず関数からアクセスできます。
リスト¶
fishでは、変数の中に複数の文字列のリスト(お好みであれば「配列」)を格納できます:
> set mylist first second third
> printf '%s\n' $mylist # prints each element on its own line
first
second
third
リストの1つの要素にアクセスするには、次のように角括弧の中に要素のインデックスを指定します:
echo $PATH[3]
fishのリストのインデックスは、他の言語のように0からではなく、1から始まります。これは「1を引く」手間を減らすためであり、 seq のような多くの一般的なUnixツールとの相性が良いためです(seq 5 は0から5ではなく、1から5を出力します)。無効なインデックスは黙って無視され、値なし(空の文字列ですらなく、引数自体が存在しない状態)になります。
括弧を使用しない場合、リストのすべての要素が個別のアイテムとしてコマンドに渡されます。つまり、 for を使ってリストを反復処理できます:
for i in $PATH
echo $i is in the path
end
これは PATH 内の各ディレクトリを個別に巡回し、それがパスに含まれていることを示す行を表示します。
blue と small というアイテムを含む変数 smurf を作成するには、次のように記述します:
set smurf blue small
リストの個々の要素を設定したり消去したりすることも可能です:
# Set smurf to be a list with the elements 'blue' and 'small'
set smurf blue small
# Change the second element of smurf to 'evil'
set smurf[2] evil
# Erase the first element
set -e smurf[1]
# Output 'evil'
echo $smurf
リスト変数の展開や代入時に負のインデックスを指定すると、インデックスはリストの「末尾」から数えられます。例えば、インデックス -1 はリストの最後の要素を指します:
> set fruit apple orange banana
> echo $fruit[-1]
banana
> echo $fruit[-2..-1]
orange
banana
> echo $fruit[-1..1] # reverses the list
banana
orange
apple
インデックスの範囲を指定することもできます。詳細は スライス を参照してください。
すべてのリストは一次元であり、他のリストを含めることはできません。ただし、デリファレンスを使用して、入れ子になったリストを模倣することは可能です。詳細は 変数展開 を参照してください。
リストが環境変数としてエクスポートされる際、それが パス変数 であるかどうかに応じて、スペースまたはコロンで区切られます:
> set -x smurf blue small
> set -x smurf_PATH forest mushroom
> env | grep smurf
smurf=blue small
smurf_PATH=forest:mushroom
fishは、名前が PATH で終わるすべての環境変数( PATH、 CDPATH、 MANPATH など)をコロンで分割し、自動的にリストを作成します。その他の変数は自動的には分割されません。
リストの状態は、 count や contains コマンドで確認できます:
> count $smurf
2
> contains blue $smurf
# blue was found, so it exits with status 0
# (without printing anything)
> echo $status
0
> contains -i blue $smurf
1
リストの優れた点は、1つの要素が1つの引数としてコマンドに渡されることです。そのため、一度リストを設定すれば、そのまま渡すことができます:
set -l grep_args -r "my string"
grep $grep_args . # will run the same as `grep -r "my string"` .
他のシェルとは異なり、fishは「ワードスプリッティング(単語の分割)」を行いません。リスト内の要素は、スペースやタブを含んでいてもそのままの状態が維持されます。
引数の処理¶
重要なリストの1つに $argv があります。これには関数やスクリプトへの引数が格納されます。例を示します:
function myfunction
echo $argv[1]
echo $argv[3]
end
この関数は、受け取った引数のうち1番目と3番目の引数を出力します:
> myfunction first second third
first
third
> myfunction apple cucumber banana
apple
banana
上記は位置引数に関するものですが、コマンドラインツールでは多くの場合、さまざまなオプションやフラグが指定されます。 $argv にはそれらが位置引数と混ざった状態で格納されます。一般的なUnixの引数処理では、短縮オプション(-h、あるいは ls -lah のようにまとめる形式)やロングオプション(--help)が利用でき、さらにそれらのオプションに引数を持たせること(--color=auto、 --position anywhere、 complete -C"git " など)も可能です。また、オプションの終わりを示す -- セパレータも使われます。これらすべてを手動で処理するのは複雑で、エラーが発生しやすくなります。
オプション処理のより堅牢なアプローチは argparse です。これは定義されたオプションをチェックして別々の変数に格納し、 $argv には位置引数のみを残します。簡単な例を示します:
function mybetterfunction
# We tell argparse about -h/--help and -s/--second
# - these are short and long forms of the same option.
# The "--" here is mandatory,
# it tells it from where to read the arguments.
argparse h/help s/second -- $argv
# exit if argparse failed because
# it found an option it didn't recognize
# - it will print an error
or return
# If -h or --help is given, we print a little help text and return
if set -ql _flag_help
echo "mybetterfunction [-h|--help] [-s|--second] [ARGUMENT ...]"
return 0
end
# If -s or --second is given, we print the second argument,
# not the first and third.
# (this is also available as _flag_s because of the short version)
if set -ql _flag_second
echo $argv[2]
else
echo $argv[1]
echo $argv[3]
end
end
オプションは $argv から「削除」されるため、この例の $argv[2] は「2番目の位置引数」を指すようになります:
> mybetterfunction first -s second third
second
オプション引数の扱い方など、argparseの詳細については argparseのドキュメント を参照してください。
パス変数¶
パス変数は、 PATH、 CDPATH、 MANPATH、 PYTHONPATH、 LANGUAGE ( ローカライズ 用)など、コロン区切りのパスリストをサポートするための特殊な変数です。名前が "PATH" (大文字小文字を区別)で終わるすべての変数は、デフォルトでパス変数になります。
パス変数は通常のリストとして動作しますが、コロンで暗黙的に結合・分割されるという点が異なります。
set MYPATH 1 2 3
echo "$MYPATH"
# 1:2:3
set MYPATH "$MYPATH:4:5"
echo $MYPATH
# 1 2 3 4 5
echo "$MYPATH"
# 1:2:3:4:5
パス変数はコロン区切りの形式でエクスポートされます。そのため、 set -x MYPATH 1 2 3 を実行すると、外部コマンドからは 1:2:3 として参照されます。
> set -gx MYPATH /bin /usr/bin /sbin
> env | grep MYPATH
MYPATH=/bin:/usr/bin:/sbin
これは他のツールとの互換性を保つためです。Unixには複数の要素を持つ変数は存在せず、それに最も近いものが PATH のようなコロン区切りのリストです。当然の理由から、各要素の中に : を含めることはできません。
変数は、 set の --path 、 --unpath オプションを使用して、パス変数としてマークしたり、マークを解除したりできます。
Special variables¶
You can change the settings of fish by changing the values of certain variables.
- PATH¶
A list of directories in which to search for commands. This is a common unix variable also used by other tools.
- Locale Variables
Locale variables such as
LANG,LC_ALL,LC_MESSAGES,LC_NUMERICandLC_TIMEset the language option for the shell and subprograms. See the section Locale variables and status language for more information.
- Color variables
A number of variable starting with the prefixes
fish_colorandfish_pager_color. See Variables for changing highlighting colors for more information.
- fish_term24bit¶
If this is set to 0, fish will not output 24-bit RGB true-color sequences but the nearest color on the 256 color palette (or the 16 color palette, if
fish_term256is 0). See also set_color. The default is 1 but for historical reasons, fish defaults to behaving as if it was 0 on some terminals that are known to not support true-color sequences.
- fish_term256¶
If this is set to 0 and
fish_term24bitis 0, translate RGB colors down to the 16 color palette. Also, if this is set to 0, set_color commands such asset_color ff0000 redwill prefer the named color.
- fish_ambiguous_width¶
controls the computed width of ambiguous-width characters. This should be set to 1 if your terminal renders these characters as single-width (typical), or 2 if double-width.
- fish_emoji_width¶
controls whether fish assumes emoji render as 2 cells or 1 cell wide. This is necessary because the correct value changed from 1 to 2 in Unicode 9, and some terminals may not be aware. Set this if you see graphical glitching related to emoji (or other "special" characters). It defaults to 2.
- fish_autosuggestion_enabled¶
controls if 自動提案 (Autosuggestions) are enabled. Set it to 0 to disable, anything else to enable. By default they are on.
- fish_transient_prompt¶
If this is set to 1, fish will redraw prompts with a
--final-renderingargument before running a commandline, allowing you to change it before pushing it to the scrollback. This enables transient prompts.
- fish_handle_reflow¶
determines whether fish should try to repaint the commandline when the terminal resizes. In terminals that reflow text this should be disabled. Set it to 1 to enable, anything else to disable.
- fish_key_bindings¶
the name of the function that sets up the keyboard shortcuts for the command-line editor.
- fish_escape_delay_ms¶
sets how long fish waits for another key after seeing an escape, to distinguish pressing the escape key from the start of an escape sequence. The default is 30ms. Increasing it increases the latency but allows pressing escape instead of alt for alt+character bindings. For more information, see the chapter in the bind documentation.
- fish_sequence_key_delay_ms¶
sets how long fish waits for another key after seeing a key that is part of a longer sequence, to disambiguate. For instance if you had bound
\cx\ceto open an editor, fish would wait for this long in milliseconds to see a ctrl-e after a ctrl-x. If the time elapses, it will handle it as a ctrl-x (by default this would copy the current commandline to the clipboard). See also Key sequences.
- fish_complete_path¶
determines where fish looks for completion. When trying to complete for a command, fish looks for files in the directories in this variable.
- fish_cursor_selection_mode¶
controls whether the selection is inclusive or exclusive of the character under the cursor (see Copy and Paste).
- fish_function_path¶
determines where fish looks for functions. When fish autoloads a function, it will look for files in these directories.
- fish_greeting¶
the greeting message printed on startup. This is printed by a function of the same name that can be overridden for more complicated changes (see funced)
- fish_history¶
the current history session name. If set, all subsequent commands within an interactive fish session will be logged to a separate file identified by the value of the variable. If unset, the default session name "fish" is used. If set to an empty string, history is not saved to disk (but is still available within the interactive session).
- fish_trace¶
if set and not empty, will cause fish to print commands before they execute, similar to
set -xin bash. The trace is printed to the path given by the --debug-output option to fish or theFISH_DEBUG_OUTPUTvariable. It goes to stderr by default. Set it toallto also trace execution of key bindings, event handlers as well as prompt and title functions.
- FISH_DEBUG¶
Controls which debug categories fish enables for output, analogous to the
--debugoption.
- FISH_DEBUG_OUTPUT¶
Specifies a file to direct debug output to.
- fish_user_paths¶
a list of directories that are prepended to
PATH. This can be a universal variable.
- umask¶
the current file creation mask. The preferred way to change the umask variable is through the umask function. An attempt to set umask to an invalid value will always fail.
- SHELL_PROMPT_PREFIX¶
if set, this string is automatically prepended to the left prompt. This is a standard environment variable that may be set by tools like systemd's
run0to indicate special shell sessions.
- SHELL_PROMPT_SUFFIX¶
if set, this string is automatically appended to the left prompt. This is a standard environment variable that may be set by tools like systemd's
run0to indicate special shell sessions.
- SHELL_WELCOME¶
if set, this string is displayed when an interactive shell starts, after the greeting. This is a standard environment variable that may be set by tools like systemd's
run0to display session information.
- BROWSER¶
your preferred web browser. If this variable is set, fish will use the specified browser instead of the system default browser to display the fish documentation.
Fish also provides additional information through the values of certain environment variables. Most of these variables are read-only and their value can't be changed with set.
- _¶
the name of the currently running command (though this is deprecated, and the use of
status current-commandis preferred).
- argv¶
a list of arguments to the shell or function.
argvis only defined when inside a function call, or if fish was invoked with a list of arguments, likefish myscript.fish foo bar. This variable can be changed.
- argv_opts¶
argparse sets this to the list of successfully parsed options, including option-arguments. This variable can be changed.
- CMD_DURATION¶
the runtime of the last command in milliseconds.
- COLUMNS and LINES
the current size of the terminal in height and width. These values are only used by fish if the operating system does not report the size of the terminal. Both variables must be set in that case otherwise a default of 80x24 will be used. They are updated when the window size changes.
- fish_kill_signal¶
the signal that terminated the last foreground job, or 0 if the job exited normally.
- fish_read_limit¶
how many bytes fish will process with read or in a command substitution.
- fish_pid¶
the process ID (PID) of the shell.
- fish_terminal_color_theme¶
a read-only variable; set to
lightordarkwhen the terminal uses a light or dark color theme respectively; set tounknownif the terminal does not report its colors. Like status terminal, this is only populated once the first interactive prompt is shown. This is used in an --on-variable event handler to update syntax highlighting variables whenever the terminal's color theme changes. See here for how to specifylightanddarkvariants in your theme.
- history¶
a list containing the last commands that were entered.
- HOME¶
the user's home directory. This variable can be changed.
- hostname¶
the machine's hostname.
- IFS¶
the internal field separator that is used for word splitting with the read builtin. Setting this to the empty string will also disable line splitting in command substitution. This variable can be changed.
- last_pid¶
the process ID (PID) of the last background process.
- PWD¶
the current working directory.
- pipestatus¶
a list of exit statuses of all processes that made up the last executed pipe. See exit status.
- SHLVL¶
the level of nesting of shells. Fish increments this in interactive shells, otherwise it only passes it along.
- status¶
the exit status of the last foreground job to exit. If the job was terminated through a signal, the exit status will be 128 plus the signal number.
- status_generation¶
the "generation" count of
$status. This will be incremented only when the previous command produced an explicit status. (For example, background jobs will not increment this).
- USER¶
the current username. This variable can be changed.
- EUID¶
the current effective user id, set by fish at startup. This variable can be changed.
- version¶
the version of the currently running fish (also available as
FISH_VERSIONfor backward compatibility).
As a convention, an uppercase name is usually used for exported variables, while lowercase variables are not exported. (CMD_DURATION is an exception for historical reasons). This rule is not enforced by fish, but it is good coding practice to use casing to distinguish between exported and unexported variables.
Fish also uses some variables internally, their name usually starting with __fish. These are internal and should not typically be modified directly.
The status variable¶
Whenever a process exits, an exit status is returned to the program that started it (usually the shell). This exit status is an integer number, which tells the calling application how the execution of the command went. In general, a zero exit status means that the command executed without problem, but a non-zero exit status means there was some form of problem.
Fish stores the exit status of the last process in the last job to exit in the status variable.
If fish encounters a problem while executing a command, the status variable may also be set to a specific value:
0 is generally the exit status of commands if they successfully performed the requested operation.
1 is generally the exit status of commands if they failed to perform the requested operation.
121 is generally the exit status of commands if they were supplied with invalid arguments.
123 means that the command was not executed because the command name contained invalid characters.
124 means that the command was not executed because none of the wildcards in the command produced any matches.
125 means that while an executable with the specified name was located, the operating system could not actually execute the command.
126 means that while a file with the specified name was located, it was not executable.
127 means that no function, builtin or command with the given name could be located.
If a process exits through a signal, the exit status will be 128 plus the number of the signal.
The status can be negated with not (or !), which is useful in a condition. This turns a status of 0 into 1 and any non-zero status into 0.
There is also $pipestatus, which is a list of all status values of processes in a pipe. One difference is that not applies to $status, but not $pipestatus, because it loses information.
例:
not cat file | grep -q fish
echo status is: $status pipestatus is $pipestatus
Here $status reflects the status of grep, which returns 0 if it found something, negated with not (so 1 if it found something, 0 otherwise). $pipestatus reflects the status of cat (which returns non-zero for example when it couldn't find the file) and grep, without the negation.
So if both cat and grep succeeded, $status would be 1 because of the not, and $pipestatus would be 0 and 0.
It's possible for the first command to fail while the second succeeds. One common example is when the second program quits early.
For example, if you have a pipeline like:
cat file1 file2 | head -n 50
This will tell cat to print two files, "file1" and "file2", one after the other, and the head will then only print the first 50 lines. In this case you might often see this constellation:
> cat file1 file2 | head -n 50
# 50 lines of output
> echo $pipestatus
141 0
Here, the "141" signifies that cat was killed by signal number 13 (128 + 13 == 141) - a SIGPIPE. You can also use fish_kill_signal to see the signal number. This happens because it was still working, and then head closed the pipe, so cat received a signal that it didn't ignore and so it died.
Whether cat here will see a SIGPIPE depends on how long the file is and how much it writes at once, so you might see a pipestatus of "0 0", depending on the implementation. This is a general unix issue and not specific to fish. Some shells feature a "pipefail" feature that will call a pipeline failed if one of the processes in it failed, and this is a big problem with it.
Locale Variables¶
The "locale" of a program is its set of language and regional settings. In UNIX, these are made up of several categories. The categories used by fish are:
- LANG¶
This is the typical environment variable for specifying a locale. A user may set this variable to express the language they speak, their region, and a character encoding. The encoding part is ignored, fish always assumes UTF-8. The actual values are specific to their platform, except for special values like
CorPOSIX.The value of
LANGis used for each category unless the variable for that category was set orLC_ALLis set. So typically you only need to set LANG.Example values are
en_US.UTF-8for the American English orde_AT.UTF-8for Austrian German. Your operating system might have alocalecommand that you can call aslocale -ato see a list of defined locales.
- LANGUAGE¶
This is treated like
LC_MESSAGESexcept that it can hold multiple values, which allows to specify a priority list of languages for translation. It's a PATH variable, like in GNU gettext.Language identifiers without a region specified (e.g.
zh) result in all available variants of this language being tried in arbitrary order. In this example, we might first look for messages in thezh_CNcatalog, followed byzh_TW, or the other way around. This is different from GNU gettext, which uses a "default" variant of the language instead. If you prefer a certain variant, specify it earlier in the list, e.g.zh_TW:zhif your preferred language iszh_TW, and you prefer any other variants ofzhover the English default. Ifzh_TWis the only variant ofzhyou want, specifyingzh_TWin theLANGUAGEvariable will result in messages which are not available inzh_TWbeing displayed in English.See also builtin _ (underscore).
- LC_ALL¶
Overrides the
LANGand all otherLC_*variables. Please useLC_ALLonly as a temporary override.
- LC_MESSAGES¶
Determines the language in which messages are displayed, see builtin _ (underscore).
- LC_NUMERIC¶
Sets the locale for formatting numbers.
Builtin commands¶
Fish includes a number of commands in the shell directly. We call these "builtins". These include:
Builtins that manipulate the shell state - cd changes directory, set sets variables
Builtins for dealing with data, like string for strings and math for numbers, count for counting lines or arguments, path for dealing with path
status for asking about the shell's status
test for checking conditions
argparse for parsing function arguments
source to read a script in the current shell (so changes to variables stay) and eval to execute a string as script
random to get random numbers or pick a random element from a list
read for reading from a pipe or the terminal
For a list of all builtins, use builtin -n.
For a list of all builtins, functions and commands shipped with fish, see the list of commands. The documentation is also available by using the --help switch.
Command lookup¶
When fish is told to run something, it goes through multiple steps to find it.
If it contains a /, fish tries to execute the given file, from the current directory on.
If it doesn't contain a /, it could be a function, builtin, or external command, and so fish goes through the full lookup.
In order:
It tries to resolve it as a function.
If the function is already known, it uses that
If there is a file of the name with a ".fish" suffix in
fish_function_path, it loads that. (If there is more than one file only the first is used)If the function is now defined it uses that
It tries to resolve it as a builtin.
It tries to find an executable file in
PATH.If it finds a file, it tells the kernel to run it.
If the kernel knows how to run the file (e.g. via a
#!line -#!/bin/shor#!/usr/bin/python), it does it.If the kernel reports that it couldn't run it because of a missing interpreter, and the file passes a rudimentary check, fish tells
/bin/shto run it.
If none of these work, fish runs the function fish_command_not_found and sets status to 127.
You can use type to see how fish resolved something:
> type --short --all echo
echo is a builtin
echo is /usr/bin/echo
Querying for user input¶
Sometimes, you want to ask the user for input, for instance to confirm something. This can be done with the read builtin.
Let's make up an example. This function will glob the files in all the directories it gets as arguments, and if there are more than five it will ask the user if it is supposed to show them, but only if it is connected to a terminal:
function show_files
# This will glob on all arguments. Any non-directories will be ignored.
set -l files $argv/*
# If there are more than 5 files
if test (count $files) -gt 5
# and both stdin (for reading input)
# and stdout (for writing the prompt)
# are terminals
and isatty stdin
and isatty stdout
# Keep asking until we get a valid response
while read --nchars 1 -l response --prompt-str="Are you sure? (y/n)"
or return 1 # if the read was aborted with ctrl-c/ctrl-d
switch $response
case y Y
echo Okay
# We break out of the while and go on with the function
break
case n N
# We return from the function without printing
echo Not showing
return 1
case '*'
# We go through the while loop and ask again
echo Not valid input
continue
end
end
end
# And now we print the files
printf '%s\n' $files
end
If you run this as show_files /, it will most likely ask you until you press Y/y or N/n. If you run this as show_files / | cat, it will print the files without asking. If you run this as show_files ., it might print something without asking because there are fewer than five files.
Shell variable and function names¶
The names given to variables and functions (so-called "identifiers") have to follow certain rules:
A variable name cannot be empty. It can contain only letters, digits, and underscores. It may begin and end with any of those characters.
A function name cannot be empty. It may not begin with a hyphen ("-") and may not contain a slash ("/"). All other characters, including a space, are valid. A function name also can't be the same as a reserved keyword or essential builtin like
iforset.A bind mode name (e.g.,
bind -m abc ...) must be a valid variable name.
Other things have other restrictions. For instance what is allowed for file names depends on your system, but at the very least they cannot contain a "/" (because that is the path separator) or NULL byte (because that is how UNIX ends strings).
Configuration files¶
When fish is started, it reads and runs its configuration files. Where these are depends on build configuration and environment variables.
The main file is ~/.config/fish/config.fish (or more precisely $XDG_CONFIG_HOME/fish/config.fish).
Configuration files are run in the following order:
Configuration snippets (named
*.fish) in the directories:$__fish_config_dir/conf.d(by default,~/.config/fish/conf.d/)$__fish_sysconf_dir/conf.d(by default,/etc/fish/conf.d/)Directories for others to ship configuration snippets for their software:
the directories under
$__fish_user_data_dir(usually~/.local/share/fish, controlled by theXDG_DATA_HOMEenvironment variable)a
fish/vendor_conf.ddirectory in the directories listed in$XDG_DATA_DIRS(default/usr/share/fish/vendor_conf.dand/usr/local/share/fish/vendor_conf.d)
These directories are also accessible in
$__fish_vendor_confdirs. Note that changing that in a running fish won't do anything as by that point the directories have already been read.
If there are multiple files with the same name in these directories, only the first will be executed. They are executed in order of their filename, sorted (like globs) in a natural order (i.e. "01" sorts before "2").
System-wide configuration files, where administrators can include initialization for all users on the system - similar to
/etc/profilefor POSIX-style shells - in$__fish_sysconf_dir(usually/etc/fish/config.fish).User configuration, usually in
~/.config/fish/config.fish(controlled by theXDG_CONFIG_HOMEenvironment variable, and accessible as$__fish_config_dir).
~/.config/fish/config.fish is sourced after the snippets. This is so you can copy snippets and override some of their behavior.
These files are all executed on the startup of every shell. If you want to run a command only on starting an interactive shell, use the exit status of the command status --is-interactive to determine if the shell is interactive. If you want to run a command only when using a login shell, use status --is-login instead. This will speed up the starting of non-interactive or non-login shells.
If you are developing another program, you may want to add configuration for all users of fish on a system. This is discouraged; if not carefully written, they may have side-effects or slow the startup of the shell. Additionally, users of other shells won't benefit from the fish-specific configuration. However, if they are required, you can install them to the "vendor" configuration directory. As this path may vary from system to system, pkg-config should be used to discover it: pkg-config --variable confdir fish.
For system integration, fish also ships a file called __fish_build_paths.fish. This can be customized during build, for instance because your system requires special paths to be used.
Future feature flags¶
Feature flags are how fish stages changes that might break scripts. Breaking changes are introduced as opt-in, in a few releases they become opt-out, and eventually the old behavior is removed.
You can see the current list of features via status features:
> status features
stderr-nocaret on 3.0 ^ no longer redirects stderr
qmark-noglob on 3.0 ? no longer globs
regex-easyesc on 3.1 string replace -r needs fewer \\'s
ampersand-nobg-in-token on 3.4 & only backgrounds if followed by a separating character
remove-percent-self off 4.0 %self is no longer expanded (use $fish_pid)
test-require-arg off 4.0 builtin test requires an argument
mark-prompt on 4.0 write OSC 133 prompt markers to the terminal
ignore-terminfo on 4.1 do not look up $TERM in terminfo database
query-term on 4.1 query the TTY to enable extra functionality
omit-term-workarounds off 4.3 skip workarounds for incompatible terminals
Here is what they mean:
stderr-nocaretwas introduced in fish 3.0 and cannot be turned off since fish 3.5. It can still be tested for compatibility, but ano-stderr-nocaretvalue will be ignored. The flag made^an ordinary character instead of denoting an stderr redirection. Use2>instead.qmark-noglobwas also introduced in fish 3.0 (and made the default in 4.0). It makes?an ordinary character instead of a single-character glob. Use a*instead (which will match multiple characters) or find other ways to match files likefind.regex-easyescwas introduced in 3.1 (and made the default in 3.5). It makes it so the replacement expression instring replace -rdoes one fewer round of escaping. Before, to escape a backslash you would have to usestring replace -ra '([ab])' '\\\\\\\\$1'. After, just'\\\\$1'is enough. Check yourstring replacecalls if you use this anywhere.ampersand-nobg-in-tokenwas introduced in fish 3.4 (and made the default in 3.5). It makes it so a&is no longer interpreted as the backgrounding operator in the middle of a token, so dealing with URLs becomes easier. Either put spaces or a semicolon after the&. This is recommended formatting anyway, andfish_indentwill have done it for you already.remove-percent-selfturns off the special%selfexpansion. It was introduced in 4.0. To get fish's pid, you can use thefish_pidvariable.test-require-argremoves builtin test's one-argument form (test "string". It was introduced in 4.0. To test if a string is non-empty, usetest -n "string". If disabled, any call totestthat would change sends a debug message of category "deprecated-test", so starting fish withfish --debug=deprecated-testcan be used to find offending calls.mark-promptmakes fish report to the terminal the beginning and end of both shell prompts and command output.ignore-terminfowas introduced in fish 4.1 and cannot be turned off since fish 4.5. It can still be tested for compatibility, but ano-ignore-terminfovalue will be ignored. The flag disabled lookup of $TERM in the terminfo database.query-termallows fish to query the terminal by writing escape sequences and reading the terminal's response. This enables features such as scrolling. If you use an incompatible terminal, you can -- for the time being -- work around it by running (once)set -Ua fish_features no-query-term.omit-term-workaroundsprevents fish from trying to work around incompatible terminals.
These changes are introduced off by default. They can be enabled on a per session basis:
> fish --features qmark-noglob,regex-easyesc
or opted into globally for a user:
> set -U fish_features regex-easyesc qmark-noglob
Features will only be set on startup, so this variable will only take effect if it is universal or exported.
You can also use the version as a group, so 3.0 is equivalent to "stderr-nocaret" and "qmark-noglob". Instead of a version, the special group all enables all features.
Prefixing a feature with no- turns it off instead. E.g. to reenable the ? single-character glob:
set -Ua fish_features no-qmark-noglob
Event handlers¶
When defining a new function in fish, it is possible to make it into an event handler, i.e. a function that is automatically run when a specific event takes place. Events that can trigger a handler currently are:
When a signal is delivered
When a job exits
When the value of a variable is updated
When the prompt is about to be shown
例:
To specify a signal handler for the WINCH signal, write:
function my_signal_handler --on-signal WINCH
echo Got WINCH signal!
end
Fish already has the following named events for the --on-event switch:
fish_promptis emitted whenever a new fish prompt is about to be displayed.fish_preexecis emitted right before executing an interactive command. The commandline is passed as the first parameter. Not emitted if command is empty.fish_posterroris emitted right after executing a command with syntax errors. The commandline is passed as the first parameter.fish_postexecis emitted right after executing an interactive command. The commandline is passed as the first parameter. Not emitted if command is empty.fish_exitis emitted right before fish exits.fish_cancelis emitted when a commandline is cleared.fish_focus_inis emitted when fish's terminal gains focus.fish_focus_outis emitted when fish's terminal loses focus.
Events can be fired with the emit command, and do not have to be defined before. The names just need to match. For example:
function handler --on-event imdone
echo generator is done $argv
end
function generator
sleep 1
# The "imdone" is the name of the event
# the rest is the arguments to pass to the handler
emit imdone with $argv
end
If there are multiple handlers for an event, they will all be run, but the order might change between fish releases, so you should not rely on it.
Please note that event handlers only become active when a function is loaded, which means you need to otherwise source or execute a function instead of relying on autoloading. One approach is to put it into your configuration file.
For more information on how to define new event handlers, see the documentation for the function command.
fish スクリプトのデバッグ¶
fish には、スクリプトの実行を任意の地点で停止できる基本的な組み込みデバッグ機能が含まれています。停止すると対話型のプロンプトが表示され、任意の fish コマンドを実行して状態の確認や変更を行うことができます(「デバッグ専用コマンド」といったものは特にありません)。例えば、 printf や set を使用して変数の値を確認・変更したり、status print-stack-trace を実行して現在のブレークポイントにどのように到達したかを確認したりできます。スクリプトの通常実行を再開するには、 exit と入力するか ctrl-d を押してください。
デバッグセッションを開始するには、制御を得たい関数やスクリプトの地点に 組み込みコマンド breakpoint を挿入し、その関数またはスクリプトを実行します。また、 TRAP シグナルのデフォルト動作はこの組み込みコマンドを呼び出すことなので、実行中のスクリプトに TRAP シグナル(kill -s TRAP <PID>)を送ることで能動的にデバッグを行うことも可能です。このデバッグプロンプトから対話的にブレークポイントを設定・変更する機能は限定的です。 funced 関数を使用して他の関数の定義を編集し、新しいブレークポイントを挿入(または既存のものを削除)することは可能ですが、現在ロードされ実行中の関数やスクリプトからブレークポイントを追加・削除することはできません。
スクリプトの問題をデバッグするもう一つの方法は、変数 fish_trace を設定することです。例えば fish_trace=1 fish_prompt と実行すると、 fish_prompt 関数の実行時に fish がどのコマンドを実行しているかを確認できます。
fish スクリプトのプロファイリング¶
特にパフォーマンスの問題を調査したい場合は、 fish を --profile /path/to/profile.log オプション付きで実行することで、指定したパスにプロファイルを保存できます。このプロファイルログには、実行の各ステップにどれだけの時間がかかったかの内訳が含まれます。
例:
> fish --profile /tmp/sleep.prof -ic 'sleep 3s'
> cat /tmp/sleep.prof
Time Sum Command
3003419 3003419 > sleep 3s
これにより、1列目に各コマンド自体の実行時間、2列目にそのコマンドとすべてのサブコマンド(関数 内部のコマンドや コマンド置換 など)を合わせた実行時間、3列目にコマンド自体が、タブ区切りで表示されます。
時間はマイクロ秒単位で表示されます。
実行時間の長いコマンドを最後に表示するには、 sort -nk2 /path/to/logfile を使うと便利です。
fish の起動時のプロファイリングには、 --profile-startup /path/to/logfile も用意されています。
詳細については fish を参照してください。

Comments¶
Anything after a
#until the end of the line is a comment. That means it's purely for the reader's benefit, fish ignores it.This is useful to explain what and why you are doing something:
There are no multiline comments. If you want to make a comment span multiple lines, start each line with a
#.Comments can also appear after a line like so: