2012-09-09 22 views
3

我希望能夠寫一個函數su_mt_user是(目前)是這樣的:擺脫使用bash函數參數蘇-c

su_mt_user() { 
    su someuser -c "$*" 
} 

的目標是能夠使用它像這樣的:

su_mt_user mt-auth --stuff etc 

這將運行命令mt-auth --stuff etc爲用戶someuser。當前版本適用於這個特定的命令,但它不能像這樣的命令:

some_filename_with_spaces="/home/user/hello there i like spaces in filenames.txt" 
su_mt_user stat "$some_filename_with_spaces" 

這失敗,出現以下錯誤:

stat: cannot stat '/home/user/hello': No such file or directory 
stat: cannot stat 'there': No such file or directory 
stat: cannot stat 'i': No such file or directory 
stat: cannot stat 'like': No such file or directory 
stat: cannot stat 'spaces': No such file or directory 
stat: cannot stat 'in': No such file or directory 
stat: cannot stat 'filenames.txt': No such file or directory 

我認爲這個錯誤是因爲即使$some_filename_with_spaces是正確的作爲一個參數傳遞給su_mt_user函數,該函數將其展開爲多個參數,其中"$*"

我也試過這個,試錯:

su_mt_user() { 
    su someuser -c "$0 [email protected]" 
} 

但還是失敗,那麼(/usr/bin/stat: cannot execute binary file(是什麼)?)

當然stat "$some_filename_with_spaces"作品如預期,從兩個當前用戶和someuser用戶。

這看起來像一些逃避的需要做,但bash知道如何做到這一點?它是否需要手動取締?如果是這樣,哪些字符需要轉義?

回答

8

要通過函數將多個參數傳遞給命令,您需要"[email protected]""[email protected]"是特別的,即使它在雙引號之間,單獨的參數以不同的單詞結束,所以它們完全按照原樣傳遞。這與[email protected]$*不帶引號不同,它會將每個含有空白的參數進行分割,並將每個生成的單詞解釋爲一個全局模式,並從"$*"開始,它將所有參數合併成一箇中間有空格的單個參數。

還有一個額外的皺紋,因爲su不直接吃掉參數,他們通過殼。 su的非選項參數作爲參數傳遞給sh -c,然後您需要爲-c提供適當的命令。

su_mt_user() { 
    su someuser -c '"$0" "[email protected]"' -- "[email protected]" 
} 
+0

謝謝!爲了防止'su'解析選項參數,必須稍加修改才能工作:'su someuser -c'「$ 0」「$ @」' - 「$ @」';否則,'su'試圖將'-a'等選項參數解釋爲自身的參數,導致錯誤。 –

+1

我也必須修改成'su suuser -c'「$ 0」「$ @」' - 「$ 0」「$ @」'因爲命令'/ bin/su -l root -c'echo args「$ @「這個」$ 0「' - abc'顯示'args bc this a'。 – HoverHell