Bash

Bash shadow a command - 與命令同名的函式

  • February 24, 2022

我有一個功能.bashrc可以自動 sudo 打開我無法寫入的文件:

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

當文件需要 sudo 時,它可以正常工作。如果沒有,它會遞歸呼叫此函式並使用 1 個 CPU 的 100%,直到我 CC。

從這個答案我看到有幾個選項,我都試過了。一個實際上有效:

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

為什麼其他選項不能像我期望的那樣工作?

(我知道這是重複的,但是很難用目前的問題標題在 SO/SE 上找到我的答案,所以我想發布一個問題,標題是我和其他人可以通過Google搜尋找到的)

別名前面的任何字元都會阻止別名觸發:

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`

解釋

問題是前兩個選項只能處理別名。它們不是特殊的重定向運算符,可以感知您是否有同名的函式或命令。他們所做的只是在別名前面放一些東西,因為別名只有在它們是管道或命令的第一部分時才會擴展

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 擴展編寫方式的一部分。因此,您可以使用這些方法讓別名隱藏命令並且仍然可以訪問實際命令。

引用自:https://unix.stackexchange.com/questions/454553