为什么脚本中的这个 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

相关内容