目的-n’$P小號1’−n’$磷小號1’-n ‘$PS1’在 .bashrc
[ -n "$PS1" ]
in的作用是什麼[ -n "$PS1" ] && source ~/.bash_profile;
?此行包含在.bashrc
dotfiles repo中。
這是檢查外殼是否是互動式的。在這種情況下,僅
~/.bash_profile
當 shell 是互動式的時才獲取文件。請參閱“這是 Shell 互動嗎?” 在 bash 手冊中,它引用了該特定的成語。(它還建議通過測試
$-
特殊變數是否包含i
字元來檢查 shell 是否是互動式的,這是解決此問題的更好方法。)
這是做什麼的
這是測試 shell 是否是互動式的一種廣泛使用的方法。請注意,它僅適用於 bash,不適用於其他 shell。所以它可以(如果很傻) for
.bashrc
,但它不起作用.profile
(由 sh 讀取,而 bash 只是 sh 的可能實現之一,而不是最常見的實現)。為什麼它有效(僅在 bash 中!)
互動式 shell 將shell 變數
PS1
設置為預設提示字元串。因此,如果 shell 是互動式的,PS1
則設置為(除非使用者.bashrc
已將其刪除,這在 頂部還不會發生.bashrc
,並且您可以認為這是一件愚蠢的事情)。在 bash 中反之亦然:非互動式 bash 實例
PS1
在啟動時未設置。請注意,此行為特定於 bash,並且可以說是一個錯誤(為什麼在 bash時bash -c '… do stuff with $var…'
不起作用?)。但是所有版本的 bash 直到並包括 4.4(我寫的最新版本)都這樣做。var``PS1
許多系統導出
PS1
到環境。這是一個壞主意,因為許多不同的 shell 使用PS1
但具有不同的語法(例如bash 的提示符轉義與zsh 的提示符轉義完全不同)。但是它已經很普遍了,在實踐中,看到它PS1
被設置並不能可靠地表明 shell 是互動式的。shell 可能繼承PS1
自環境。為什麼在這裡(錯誤)使用它
.bashrc
是 bash 在互動時在啟動時讀取的文件。一個鮮為人知的事實是 bash 還讀取.bashrc
了一個登錄 shell,並且 bash 的啟發式方法得出結論認為這是一個遠端會話(bash 檢查其父級是否為rshd
或sshd
)。在第二種情況下,不太可能PS1
在環境中設置,因為還沒有執行點文件。但是,程式碼使用此資訊的方式適得其反。
- 如果 shell 是互動式 shell,則它
.bash_profile
在該 shell 中執行。但是.bash_profile
是登錄時腳本。它可能會執行一些旨在每個會話僅執行一次的程序。它可能會覆蓋使用者在執行該 shell 之前故意設置為不同值的一些環境變數。.bash_profile
在非登錄 shell 中執行具有破壞性。- 如果 shell 是非互動式遠端登錄 shell,則不會載入
.bash_profile
. 但這是載入.bash_profile
可能有用的情況,因為非互動式登錄 shell 不會自動載入/etc/profile
和~/.profile
.我認為人們這樣做的原因是針對通過 GUI 登錄(一種非常常見的情況)並且將環境變數設置放入
.bash_profile
而不是.profile
. 大多數 GUI 登錄機制呼叫.profile
但不呼叫.bash_profile
(讀取.bash_profile
需要執行 bash 作為會話啟動的一部分,而不是 sh)。使用此配置,當使用者打開終端時,他們將獲得環境變數。但是,使用者不會在 GUI 應用程序中獲得他們的環境變數,這是一個非常常見的混淆來源。這裡的解決方案是使用.profile
而不是.bash_profile
設置環境變數。在兩者之間添加一座橋樑,.bashrc
並.bash_profile
產生比它解決的問題更多的問題。該怎麼做
有一種直接、可移植的方式來測試目前 shell 是否是互動式的:測試該選項是否
-i
被啟用。case $- in *i*) echo "This shell is interactive";; *) echo "This shell is not interactive";; esac
這對於僅在 shell 是非互動式的情況
.bashrc
下**讀取.profile
**很有用——即與程式碼的作用相反!如果 bash 是(非互動式)登錄 shell,請閱讀.profile
,如果它是互動式 shell,請不要閱讀。if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi