Bash

bash腳本中的type命令,未顯示所有路徑

  • November 19, 2021

當我echo "${PATH}" | tr -s ':' '\n' | nl從 bash 腳本中鍵入並在終端上時,我得到相同的結果:

    1  /home/nikhil/Documents/Git/Cs/Architecture/bin
    2  /home/nikhil/.local/bin
    3  /home/nikhil/opt/.nvm/versions/node/v16.13.0/bin
    4  /home/nikhil/opt/bin
    5  /usr/local/sbin
    6  /usr/local/bin
    7  /usr/sbin
    8  /usr/bin
    9  /sbin
   10  /bin
   11  /usr/games
   12  /usr/local/games
   13  /snap/bin
   14  /home/linuxbrew/.linuxbrew/bin
   15  /home/linuxbrew/.linuxbrew/sbin
   16  /home/nikhil/.cargo/bin
   17  /home/nikhil/.cabal/bin
   18  /home/nikhil/opt/go/bin
   19  /home/nikhil/.ruby/bin
   20  /home/linuxbrew/.linuxbrew/opt/fzf/bin

但是當我在 bash 腳本和終端上鍵入以下內容時,我會得到不同的結果:

# From Terminmal
$ type pandoc
pandoc is aliased to `/usr/bin/pandoc'
pandoc is /usr/bin/pandoc
pandoc is /home/linuxbrew/.linuxbrew/bin/pandoc
pandoc is /home/nikhil/.cabal/bin/pandoc
# From inside bash script
pandoc is /usr/bin/pandoc

為什麼typebashscript 內部和終端的輸出不同?如何使 bash 腳本type輸出與終端的輸出相同?

看起來您已type別名為type -a. 您從終端執行的任何 shell 腳本都不會繼承別名,並且腳本預設以非互動模式執行。

因為腳本在非互動式 shell 中執行,~/.bashrc當 bash 執行腳本時不會被獲取,因此不會載入在那裡定義的別名。

如果沒有-a,type將*“指示如果將其用作命令名稱將如何解釋”* - 即它將向您顯示實際執行的內容。使用-a,它將向您顯示所有可能的匹配項- $PATH(直接和通過以下符號連結)中的執行檔、別名、函式)

例如在我的系統上,grep是別名:

$ type grep
grep is aliased to `grep --directories=skip --binary-files=without-match'

$ type -a grep
grep is aliased to `grep --directories=skip --binary-files=without-match'
grep is /bin/grep

$ type -P grep
/bin/grep

如果我type在 bash 的(非互動式)實例中執行,我的別名不會被繼承:

$ bash -c 'type grep'
grep is /bin/grep

如果我強制 bash 以互動模式執行,它將source ~/.bashrc(反過來,它會獲取我的~/.bash-aliases文件)。

$ bash -i -c 'type grep'
grep is aliased to `grep --directories=skip --binary-files=without-match'

注意:僅僅讓你的腳本bash -i用作它們的解釋器並不是一個好主意。相反,在腳本本身中定義腳本所需的任何別名或函式,或從另一個文件中獲取它們。或者只是將命令與腳本中需要的任何選項一起使用 - 別名可以方便地減少重複輸入,這在腳本中並不是真正需要的。BTW,type-P選項通常是腳本中最有用的選項。

help type

type: type [-afptP] name [name ...]

Display information about command type.

For each NAME, indicate how it would be interpreted if used as a
command name.

Options:
  -a        display all locations containing an executable named NAME;
            includes aliases, builtins, and functions, if and only if
            the `-p` option is not also used

  -f        suppress shell function lookup

  -P        force a PATH search for each NAME, even if it is an alias,
            builtin, or function, and returns the name of the disk file
            that would be executed

  -p        returns either the name of the disk file that would be executed,
            or nothing if `type -t NAME` would not return `file`

  -t        output a single word which is one of `alias`, `keyword`,
            `function`, `builtin`, `file` or ``, if NAME is an alias,
            shell reserved word, shell function, shell builtin, disk file,
            or not found, respectively

Arguments:
  NAME      Command name to be interpreted.

Exit Status:
Returns success if all of the NAMEs are found; fails if any are not found.

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