如何在命令中傳遞參數而不執行參數內容?
好日子。
我有一個小問題。我在 bash 腳本中有這個功能
function denyCheck(){ file=$(readlink -f $(which $(printf "%s\n" "$1"))) if [[ -x $file ]];then return false else return true fi } denyCheck "firefox"
這個函式我向她傳遞了一個字元串,什麼是命令,這解決了命令所在的原始路徑(例如:/usr/lib/firefox/firefox.sh),如果文件是可執行的,則返回 true,否則返回 false。
但問題是…參數(在範例中為“firefox”)將其作為命令執行並打開瀏覽器 firefox。
我該怎麼做才能使參數不執行它?
非常感謝。
應該是:
cmd_canonical_path() { local cmd_path cmd_path=$(command -v -- "$1") && cmd_path=$(readlink -e -- "$cmd_path") && [ -x "$cmd_path" ] && REPLY=$cmd_path } 2> /dev/null
然後使案例如:
if cmd_canonical_path firefox; then printf '%s\n' "firefox found in $REPLY executable" else printf >&2 '%s\n' "no executable file found for firefox" fi
在 shell 中,所有命令都有一個退出狀態,指示成功 (0) 或失敗(任何其他數字,其值可以幫助區分不同類型的失敗)。
例如,如果執行該命令的程序對文件(或目錄)具有執行權限,則該
[
命令在傳遞-x
和as 參數時將返回 true。/path/to/some/file``]``/path/to/some/file
一個函式也可以有一個退出狀態,這是它在返回之前執行的最後一個命令的退出狀態(或者
return
如果在那裡呼叫,則傳遞給的數字)。命令的成功或失敗狀態由 shell 結構檢查,例如
if
//語句until
或其while
布爾運算符||
和&&
. 如果您願意,命令是 shell 的布爾值。
cmd1 && cmd2 && cmd3
返回成功 / true 是全部cmd1
,cmd2
並且cmd3
成功。如果失敗,cmd2
甚至不會執行cmd1
,對於cmd3
.因此,
cmd_canonical_path
如果command -v -- "$1"
(用於查找命令並輸出其路徑的標準內置¹命令²;雖然which
是一些類似的命令,但僅適用於 csh 使用者)然後readlink -e
成功(類似於規範化readlink -f
路徑,但如果不能,則會返回失敗) whilereadlink -f
將盡最大努力)成功**,**然後目前程序對該文件具有執行權限,然後(並且僅在那時)將該路徑成功分配給REPLY
4變數(普通分配總是成功的)。如果不是,該函式將返回失敗:該
cmd && cmd && cmd
鏈中第一個失敗的命令的退出狀態。您還會注意到,
$REPLY
如果無法確定該命令的規範路徑或您無法執行該命令,則該命令將被單獨保留且不會被修改。您的方法的其他一些問題:
- 這
$(printf '%s\n' "$1")
沒有多大意義。在 sh/bash 中,它與$1
(至少在預設值 的情況下$IFS
)相同,並且同樣錯誤,因為它沒有被引用。如果要將第一個位置參數的內容傳遞給命令,則語法為cmd "$1"
.- 當您希望傳遞給命令的一些任意數據被視為非選項參數時,您需要在
--
標記選項結束的參數之後傳遞它:which -- "$1"
,readlink -f -- "$(...)"
.return
將(可選)數字作為參數(函式的退出程式碼),而不是true
/false
(您似乎也將它們顛倒了,因為您說如果文件是可執行的,函式將返回 true)。如果未傳遞數字,則函式的退出狀態將是函式中執行的最後一個命令的退出狀態。所以if cmd; then return 0; else return 1; fi
最好寫成 justcmd; return
。雖然在這裡你甚至不需要return
因為cmd
([[ -x $file ]]
在你的情況下)是你函式中的最後一個命令。- 您在沒有首先檢查它是否成功的情況下盲目地傳遞
which
(錯誤地因為您忘記了--
和引用$(...)
)的輸出。readlink
最後一點,如果您使用
zsh
代替bash
,您可以這樣做:firefox_path==firefox firefox_canonical_path=$firefox_path:P
獲取
firefox
命令的路徑。=firefox
展開到firefox
命令的路徑,如果找不到,則中止 shell 並返回錯誤。如果需要,您可以在一個*always
塊*中攔截該錯誤。:P
修飾符對它所應用的參數執行realpath()
等效操作,類似於 GNUreadlink -f
所做的。無需檢查執行權限,因為zsh
’=cmd
運算符只會擴展為可執行的路徑。¹ 並且由於它是 shell 的內置功能,您可以在 shell 手冊中找到它的文件。對於
bash
,參見info bash command
例如。² 需要注意的是,
command -v cmd
輸出cmd
是cmd
一個函式或 shell 內置,這可能是一個問題。³ 一個規範的絕對路徑以 開頭
/
,沒有符號連結組件(它們都被解析為它們的目標),沒有.
/組件,沒有兩個或多個s 的..
序列。/
4
$REPLY
通常使用(儘管這只是一個約定)作為函式或 shell 內置函式的預設變數以返回值。或者,您的函式可以輸出結果,呼叫者將執行firefox_path=$(cmd_canonical_path firefox)
.