![如何正确使用命令替换作为文件列表中带有空格的命令的参数?](https://linux22.com/image/211001/%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E4%BD%BF%E7%94%A8%E5%91%BD%E4%BB%A4%E6%9B%BF%E6%8D%A2%E4%BD%9C%E4%B8%BA%E6%96%87%E4%BB%B6%E5%88%97%E8%A1%A8%E4%B8%AD%E5%B8%A6%E6%9C%89%E7%A9%BA%E6%A0%BC%E7%9A%84%E5%91%BD%E4%BB%A4%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%9F.png)
假设我有一个名为 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 个文件:"a
、space"
和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)