shebang 中的多個參數
我想知道是否存在通過 shebang 行 (
#!
) 將多個選項傳遞給執行檔的通用方法。我使用 NixOS,我編寫的任何腳本中 shebang 的第一部分通常是
/usr/bin/env
. 然後我遇到的問題是,之後的所有內容都被系統解釋為單個文件或目錄。例如,假設我想編寫一個腳本以
bash
在 posix 模式下執行。寫shebang的天真方式是:#!/usr/bin/env bash --posix
但嘗試執行生成的腳本會產生以下錯誤:
/usr/bin/env: ‘bash --posix’: No such file or directory
我知道這篇文章,但我想知道是否有更通用和更清潔的解決方案。
編輯:我知道對於Guile腳本,有一種方法可以實現我想要的,記錄在手冊的第 4.3.4 節中:
#!/usr/bin/env sh exec guile -l fact -e '(@ (fac) main)' -s "$0" "$@" !#
這裡的訣竅是第二行(以 開頭
exec
)被解釋為程式碼,sh
但是,在#!
…!#
塊中,作為註釋,因此被 Guile 解釋器忽略。不可能將此方法推廣到任何解釋器嗎?
第二次編輯:玩了一會兒之後,似乎對於可以從中讀取其輸入的解釋器,
stdin
以下方法會起作用:#!/usr/bin/env sh sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;
不過,這可能不是最優的,因為該
sh
過程會一直持續到解釋器完成其工作。任何回饋或建議將不勝感激。
沒有通用的解決方案,至少如果您需要支持 Linux,則沒有,因為Linux 核心將 shebang 行中第一個“單詞”之後的所有內容視為單個參數。
我不確定 NixOS 的限制是什麼,但通常我會把你的 shebang 寫成
#!/bin/bash --posix
或者,在可能的情況下,在腳本中設置選項:
set -o posix
或者,您可以使用適當的 shell 呼叫讓腳本自行重新啟動:
#!/bin/sh - if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "$@"; fi shift # Processing continues
這種方法可以推廣到其他語言,只要您找到一種方法讓目標語言忽略前幾行(由 shell 解釋)。
GNU
coreutils
’env
從 8.30 版開始提供了一種解決方法,有關詳細資訊,請參閱unode的答案。(這在 Debian 10 及更高版本、RHEL 8 及更高版本、Ubuntu 19.04 及更高版本等中可用。)
雖然不完全可移植,但從 coreutils 8.30 開始,根據其文件,您將能夠使用:
#!/usr/bin/env -S command arg1 arg2 ...
所以給出:
$ cat test.sh #!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too
你會得到:
% ./test.sh $0 is '/usr/local/bin/showargs' $1 is 'here' $2 is 'is another' $3 is 'long' $4 is 'arg' $5 is '-e' $6 is 'this and that ' $7 is 'too' $8 is './test.sh'
如果你好奇的話
showargs
是:#!/usr/bin/env sh echo "\$0 is '$0'" i=1 for arg in "$@"; do echo "\$$i is '$arg'" i=$((i+1)) done