假设我有一个名为 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)