跑步时
/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"
在代码的其他部分,双引号几乎总是正确的做法,无论你在哪里使用变量。 有可以省略引号的情况. 不应引用的情况相对较少。
单引号是防止单词分裂的另一种方法,但由于它也会防止变量扩展(事实上:任何扩展),所以在我们的例子中它根本没有用。