為什麼腳本中的 gpg 指令在貼到 shell 中時表現不同?

為什麼腳本中的 gpg 指令在貼到 shell 中時表現不同?

這是一個腳本,它按順序使用兩個不同的對稱密碼對稱地加密/解密檔案。

#!/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

相關內容