這是一個腳本,它按順序使用兩個不同的對稱密碼對稱地加密/解密檔案。
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Arguments: enc|dec filename"
exit
fi
E="gpg -o - --symmetric --cipher-algo"
D="gpg -o - --decrypt"
ERR="2>/dev/null"
if [ "$1" = "enc" ]; then
$E AES $2 | $E TWOFISH -
elif [ "$1" = "dec" ]; then
$D $2 ${ERR} | $D - ${ERR}
else
echo "Arguments: enc|dec filename"
exit
fi
當我運行時./doublecrypt dec /tmp/test.encrypted
出現錯誤
usage: gpg [options] --decrypt [filename]
usage: gpg [options] --decrypt [filename]
如果我改變線路
$D $2 ${ERR} | $D - ${ERR}
到
echo "$D $2 ${ERR} | $D - ${ERR}"
它列印
gpg -o - --decrypt /tmp/xenc 2>/dev/null | gpg -o - --decrypt - 2>/dev/null
如果我將其複製並貼上到 bash 中,它就會正確運行。
echo
那麼,如果我刪除並讓 bash 腳本直接評估它(就像原始形式一樣),為什麼它不起作用?
我運行的是 Ubuntu Saucy,bash 是我的 shell。
答案1
簡短回答:參見BashFAQ #50:我試著將命令放入變數中,但複雜的情況總是失敗!。
長答案:由於 shell 解析命令列各種元素的順序,您遇到了麻煩;具體來說,它在處理過程中大約一半時擴展變數引用(例如${ERR}
)——在處理完引號、轉義和重定向等內容之後。在您的情況下,重定向部分很重要:當 shell 擴展為 時${ERR}
,2>/dev/null
它已經在尋找重定向但沒有找到任何重定向,因此它只是將其2>/dev/null
視為命令的參數,然後gpg
拒絕它,因為它沒有任何意義。
基本上,將命令(或命令元素)儲存在變數中是錯誤的方法。變數用於數據,而不是可執行程式碼。在這種情況下,您最好使用函數來代替:
e() {
gpg -o - --symmetric --cipher-algo "$@"
}
d() {
gpg -o - --decrypt "$@" 2>/dev/null
}
if [ "$1" = "enc" ]; then
e AES "$2" | e TWOFISH -
elif [ "$1" = "dec" ]; then
d "$2" | d -
else
echo "Arguments: enc|dec filename"
exit
fi
請注意,我還$2
用雙引號引起來,以防止其值受到 shell 解析過程的後半部分的影響。
答案2
嘗試更改$D $2 ${ERR} | $D - ${ERR}
為:
$( $D $2 ${ERR} | $D - ${ERR} )
另外,使用程式的完整路徑gpg
,例如:
/usr/local/bin/gpg