Bash シャドウコマンド - コマンドと同じ名前の関数

Bash シャドウコマンド - コマンドと同じ名前の関数

.bashrc書き込み不可能なファイルを自動的にsudosする機能があります。

vim() {
    if [ -w "$1" ]; then
        \vim "$1"
    else
        sudo env HOME="$HOME" \vim -u ~/.vimrc "$1"
    fi
}

ファイルにsudoが必要な場合は正常に動作します。それ以外の場合は、この関数を再帰的に呼び出し、I CC まで CPU を 100% 使用します。

この回答ではいくつかのオプションがあり、すべて試してみました。実際に働くもの:

'vim' "$1" #fails
\vim "$1" #fails
command vim "$1" #Works!

他のオプションが期待どおりに機能しないのはなぜですか?

(重複していることはわかりますが、現在の質問のタイトルではSO / SEで答えを見つけるのが難しいので、私と他の人がインターネット検索で見つけることができるタイトルで質問を投稿する必要があると思いました。)

ベストアンサー1

エイリアスの前に文字がある場合、エイリアスは実行されません。

alias ls='ls -la'
ls foo.txt     #will run ls -la foo.txt
\ls foo.txt    #will run ls foo.txt
'ls' foo.txt   #will run ls foo.txt
'ls foo.txt'   #will run ls foo.txt

ただし、これが関数を停止するわけではなく、command同じ名前の関数を生成する場合は、デフォルトの組み込み関数を参照する必要があります。

ls () {
    echo "not an alias"
}
alias ls='echo "an alias"'

ls foo.txt          #will echo "an alias"
\ls foo.txt         #will echo "not an alias"
'ls' foo.txt        #will echo "not an alias"
command ls foo.txt  #will actually run `ls`

説明する

問題は、最初の2つのオプションがエイリアスのみを処理できることです。同じ名前の関数やコマンドがあるかどうかを検出する特別なリダイレクト演算子ではありません。エイリアスはパイプまたはコマンドの最初の部分である場合にのみ拡張されるため、エイリアスの前に何かを入れるだけです。

alias v='sudo vim'
v x.txt
#automatically expands "v" to "sudo vim" and then does the rest of the command
# v x.txt ==> sudo vim x.txt

Bashは、知っているエイリアスのリスト(を使用して取得できます)を使用してaliasコマンドの最初の単語を拡張しようとします。エイリアスは引数を使用せず、最初の単語(スペースで区切られた)のみが可能です。vim x.txt に慣れるsudo vimim x.txt正しく拡張するには、コマンドで上記のエイリアスを使用して拡張します。

ただし、一重引用符内の内容は拡張されません。変数が表す内容の代わりにecho '$USER'リテラルが印刷されます。$USERまた、bashは\xx主に)拡張されます。これは、別名をエスケープするために特別に追加された追加のメソッドではなく、単にbash拡張が作成される方法の一部にすぎません。したがって、これらの方法を使用すると、エイリアスがコマンドを非表示にしても、実際のコマンドには引き続きアクセスできます。

おすすめ記事