Bashエイリアス-優先順位/シャドウイング(/非表示/失敗)
.bashrcにいくつかのエイリアスを(この順序で)設定しています:
alias ls="lsc"
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
alias
調達後の確認:
alias ls='lsc'
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'
新しくエイリアスされたものを問題ls
なく実行でき、lscエイリアスにチェーンされてから、lscエイリアスに関連付けられたコマンドを実行します。私も走ることができlscR
、期待通りに動作します。
lsc
しかし、自分で実行しようとすると、次のようになります。
$ lsc
lsc: command not found
このシナリオでシェルがlscエイリアスをシャドウ/非表示にしているように見える理由はありますか?(ここで同じ結果を得るために「ls」を実行できるのに「lsc」を実行するのは無意味だと思いますが、このシナリオでのシェルの動作を理解しようとしています)。
編集:質問の回答で提供される(bash)シェルの動作に関する以下の回避策。
元の質問に対して、いくつかの非常に役立つ回答が提供されています。回答で説明されている拡張動作を短絡するために、2番目のエイリアスが既にエイリアス化されているコマンドを拡張しようとするのを防ぐ方法が少なくとも2つあるようです。たとえば、をalias cmd='cmd --stuff'
呼び出すネイティブコマンドをオーバーライドしているcmd
場合は、次の方法で、cmd
他のエイリアス内のネイティブの代わりに「cmd」エイリアスが使用されないようにすることができます。
(この最初のアプローチに対するwjandreaのコメントに感謝します)
cmd
他のエイリアスで「コマンド」を前に付ける例:alias other-cmd-alias='command cmd --other-stuff'
または、
- 同様に、バックスラッシュ ''を前に付けることで、他のエイリアス内でエイリアスをエスケープできます(コマンドラインでも実行できます)
alias other-cmd-alias='\cmd --other-stuff'
。
回答
Bashでは、エイリアスにエイリアスを含めることができますが、無限ループに対する保護が組み込まれています。あなたの場合、入力するとlsc
、bashは最初にエイリアスを次のように展開します。
ls -Flatr --color=always
ls
はエイリアスでもあるため、bashはそれを次のように展開します。
lsc -Flatr --color=always
lsc
はエイリアスですが、かなり賢明なことに、bashはそれを2回拡張することを拒否します。、という名前のプログラムがあった場合lsc
、bashはそれを実行します。しかし、ありません、そしてそれはあなたが得る理由ですcommand not found
。
補遺
lscR
実行時は異なります。lscR
に展開:
ls -FlatrR --color=always
ls
はエイリアスなので、これは次のように展開されます。
lsc -FlatrR --color=always
lsc
はエイリアスなので、これは次のように展開されます。
ls -Flatr --color=always -FlatrR --color=always
ls
すでに1回拡張されているため、bashは2回目の拡張を拒否します。と呼ばれる実際のコマンドがls
存在するため、実行されます。
歴史
Schilyがコメントで指摘しているように、bashはkshからエイリアスを2回拡張しないという概念を借用しました。
さておき
エイリアスは便利ですが、それほど強力ではありません。引数の置換など、エイリアスを使用して複雑なことをしたい場合は、しないでください。代わりにシェル関数を使用してください。
bashマニュアルから:
置換テキストの最初の単語はエイリアスについてテストされますが、展開されているエイリアスと同一の単語は2回目に展開されません。これは、たとえば
ls
「ls -F
」にエイリアスを付けることができ、Bashが置換テキストを再帰的に展開しようとしないことを意味します。
でls
、エイリアス、ls
に展開されlsc
、その後、再びls -Flatr --color=always
、それ以来エイリアスの展開は、そこに停止しls
、もともと拡張されていました。そのため、コマンドは正常に実行ls
され、外部コマンドに解決されます。
でlsc
、エイリアス、lsc
に展開されls -Flatr --color=always
、その後、ls
今まで展開されているlsc
し、そこので、エイリアスの展開は、停止しlsc
、もともと拡張されていました。したがって、bashは他のを知らないため、コマンドは失敗しますlsc
。