如何正确使用命令替换作为文件列表中带有空格的命令的参数?

如何正确使用命令替换作为文件列表中带有空格的命令的参数?

假设我有一个名为 FILES 的文件,其内容为:

/path/to/something
/path/to/something/else
/path/to/something/else/with/a space
/path/to/something/else/again

如果我尝试使用这样的命令替换:head -n 1 $(cat FILES)

我会有 :

head: cannot open 'a' for reading: No such file or directory
head: cannot open 'space' for reading: No such file or directory

使用转义字符\或分隔符""无法解决''此问题。 (我不知道为什么......)

执行此操作的正确方法是什么?

编辑 :显然我的问题比我想象的要简单。这是工作:

head "a space" no_space

但这不是:

FILES='"a space" no_space'; echo $FILES; head $FILES

这里它被视为 3 个文件:"aspace"no_space
那么...如何要求 shell 不要忽略分隔符? (或转义字符)

编辑2:

找到了一个解决方案:

while read line; do head "$line"; done < FILES

有人有不使用循环的东西吗?

答案1

将每一行(以换行符结尾)放入允许文件名中包含空格(但不允许 NUL 或换行符)的数组中的正确解决方案是:

$ readarray -t files <FILES

$ printf '<%s>\n' "${files[@]}"
</path/to/something>
</path/to/something/else>
</path/to/something/else/with/a space>
</path/to/something/else/again>

"${files[0]}"然后您可以使用直到最后一个索引的每个值。

请引用每个参数以避免 shell 执行拆分的影响。

如果您只想获取 FILES 中列出的每个文件的第一行,您可以执行以下操作:

$ readarray -t files <FILES
$ head -n1 "${files[@]}"
first line on first file
first line on second file
...
...

答案2

如果您在脚本之前使用它应该非常有用:set -f。感谢 ikkachu 的建议。

解决方案1

环境IFS=$'\n'

IFS=$'\n' ; head -1  $(cat data)

解决方案2

另一种可能的解决方案是在定义的路径之间添加双引号FILES

"/path/to/something"
"/path/to/something/else"
"/path/to/something/else/with/a space"
"/path/to/something/else/again"

xargs并在得到结果的帮助下:

cat FILES | xargs head -n1
#or
xargs head -n1 < FILES
#or
xargs head -n1 <<< $(cat FILES)

相关内容