使用命令输出(带空格)作为其他命令输入(BASH)

时间:2021-01-07 00:09:24

标签: linux bash

有人知道这是为什么吗?

cat `echo "FilenameWithoutSpaces.txt"` # shows file content

标准输出:

显示文件内容

这不是吗?

cat `echo "Filename\ With\ Spaces.txt"` # trying to show "Filename With Spaces.txt" content

标准输出:

cat: 'Filename': 没有那个文件或目录

cat: 'With': 没有那个文件或目录

cat:Spaces.txt:没有那个文件或目录

将输出(带空格)作为另一个命令的输入传递的正确方法是什么?

上面的例子是我需要的一个简化案例。我必须做的是:

使用命令返回的文件列表(可能包含空格)作为另一个命令的参数。

2 个答案:

答案 0 :(得分:0)

对于这种特殊情况:

cat "$(echo "Filename\ With\ Spaces.txt")"

因为这个案例有点做作,我不能真正说出你的实际情况是什么才是正确的。 “文件列表”是什么意思?那是由换行符分隔的文件列表吗?您将如何处理名称中包含换行符的文件?它是空分隔文件的列表,还是逗号分隔的列表?一般来说,我认为正确的解决方案是禁止在文件名中使用空格。如果这不是一个选项,一般原则是始终在任何可能包含 IFS 元素的字符串周围加上引号。

不过。 (注意这个“然而”应该被理解为“以下是一个可怕的黑客,永远不应该做,因为正确的方法是禁止在文件名中使用空格”)。假设“文件列表”是指通过字符串中的换行符将每个名称与下一个名称区分开来,您可以尝试以下操作:

printf '1st name\n2nd name\n' | { a=(); while read arg; do a+=("$arg"); done; 
    cmd "${a[@]}"
}

上面将调用 cmd 并将每一行作为单个参数。要求输入列表以零分隔会更合理,这将允许您将 xargs 与以下内容一起使用:

printf '1st name\0002nd name\000' | xargs -0 cmd

除非您正确定义“文件列表”的含义,否则不可能有可靠的解决方案。

答案 1 :(得分:0)

这是由于字符串的处理方式和传递的方式是 bash 中的参数。当您运行 echo "Filename\ With\ Spaces.txt" 时,输出为 Filename With Spaces.txt,这正是您所期望的。所以完整的命令本质上与 cat Filename With Spaces.txt 相同,并且 cat 试图找到名称为 Filename、With 和 Spaces.txt 的 3 个文件。

当 bash 查找这些时,它不太可能找到它们并吐出您看到的那些错误消息。如果没有空格,文件名将作为单个参数读取,因此您不会遇到相同的问题。

要强制命令使用和不使用空格,您需要在命令替换周围添加引号:

cat "`echo "Filename\ With\ Spaces.txt"`"

此命令将扩展 echo 的输出并将其保留为单个参数。