这一行 bash 中的模糊重定向在哪里?

这一行 bash 中的模糊重定向在哪里?

跑步时

/usr/bin/borg info --last 1 --json ${repo} | jq -r '.archives | first | .end' |  python3 -c "import arrow, sys ; print(arrow.get(sys.stdin.read()).isoformat())" > /etc/local/borg-lastrun-${repo}-${tobackup}.txt

我明白了

/etc/local/borg.sh: line 27: /etc/local/borg-lastrun-${repo}-${tobackup}.txt: ambiguous redirect

${repo}${tobackup}已设置)

歧义在哪里?

我怀疑这可能是jq代码('.archives | first | .end'),因为引号外面和里面有多个管道(?)但我不确定(如果是这种情况,也不知道如何修复它)

答案1

${repo}在 Bash 中,未加引号的变量(例如或)的值$repo会经历单词拆分和文件名生成。这意味着通常情况下,未加引号的变量可以生成多个单词。或者更少;如果它未设置或为空,则它将生成零个单词。

如果出现类似> ${repo}或的重定向> $repo,则除一个单词外,其他单词都是错误的。从技术上讲,以下内容可能有效(但事实并非如此):

# wrong
foo='bar baz'
echo qux > $foo

如果它有效,那么最后一行就相当于

echo qux > bar baz

哪个已验证并相当于

echo qux baz > bar

如果故意将参数 (此处:baz) 隐藏在看似重定向 (此处:> $foo) 的语句中,则是一种不好的做法;如果无意中这样做,则可能是一个有害的错误。Bash 不允许您这样做。

(其实我怀疑这并不是因为 Bash 关心,而是因为它的解析器的工作方式:我思考它提前识别重定向,将它们与实际命令分开,并将它们处理为有点脱节的。将参数重新注入命令会很麻烦,不值得这么麻烦。但这是我猜

手动的明确指出[强调我的]:

重定向运算符 […] 后面的单词,除非另有说明,否则将进行括号扩展、波浪符号扩展、参数扩展、命令替换、算术扩展、引号删除、文件名扩展和单词拆分。如果扩展为多个单词,Bash 将报告错误。

这是你得到的“不明确的重定向”错误。手册上说的是“多于一个单词”;试验表明在“零词”(变量为空或未设置)的情况下也会出现相同的错误。

正确的单词数是 1。当涉及许多变量时,这也适用,例如在您的 中/etc/local/borg-lastrun-${repo}-${tobackup}.txt。此字符串不能扩展为零个单词,但(取决于变量的值)它可以扩展为多个单词。确保字符串被解释为单个单词的正确方法是将其用双引号括起来:

… > "/etc/local/borg-lastrun-${repo}-${tobackup}.txt"

在代码的其他部分,双引号几乎总是正确的做法,无论你在哪里使用变量。 有可以省略引号的情况. 不应引用的情况相对较少。

单引号是防止单词分裂的另一种方法,但由于它也会防止变量扩展(事实上:任何扩展),所以在我们的例子中它根本没有用。

相关内容