アップデート
この回答は 10 年前の 2010 年に書かれました。fish の最近のバージョン (私は 3.1.2 でテストしました) が更新され、set cmd ls; $cmd
現在有効です。
どのように
これは、コマンド置換がパラメーター展開に属し、コマンドとして許可されていないためです。
同様の例:
で:
tmpls=ls
$tmpls
しかし、魚では:
% set cmd ls; $cmd
fish: Variables may not be used as commands.
...
どうして
要するに、検証可能性に優れています
この記事では、詳細について説明します。
通常のシェルでは変数をコマンドとして使用できるため、スクリプトの構文を確実にチェックすることはできません。たとえば、この bash/zsh コードのスニペットは、運次第で合法である場合とそうでない場合があります。ラッキーだと思いますか?
if true; then if [ $RANDOM -lt 1024 ]; then END=fi; else END=true; fi; $END
bash と zsh はどちらも、ユーザーがリターン キーを押したときに、現在のバッファー内のコマンドが終了したかどうかを判断しようとしますが、このような問題のために失敗することがあります。さらに悪いことに、この完全に合法的なコードは bash によって拒否されます。
FI=fi; foo() { if true; then true; $FI; }
変数はコマンドとして許可されていないため、Fish はこの種の問題を回避します。コマンドとして変数を使用してできることはすべて、eval コマンドまたは関数を使用して、よりクリーンな方法で実行できます。
同じ理由で、コマンド置換はコマンドとして許可されていません。
(注: 'if' と 'fi' は単純なコマンドではなく予約語であるため、引用された例は公平ではありません。以下のコメントを参照してください。)