我的makefile
的一部分如下:
list: all
for f in \
`less fetch/list.txt`; \
do \
echo $$f; \
...
done
fetch/list.txt
包含文件列表:
path/file1.ml
path/file2.ml
path/file 3.ml
path/file 4.ml
问题是,即使文件名中允许空格,make list
也会显示:
path/file1.ml
path/file2.ml
path/file
3.ml
path/file
4.ml
有没有人知道让每一行完整地读取,无论空格如何?
答案 0 :(得分:5)
这是一种方法:
list:
while IFS= read -r n ; do echo "line: $$n" ; done < list.txt
这是在行动:
$ cat list.txt
abc
def
123 456
$ gmake
while read n ; do echo "line: $n" ; done < list.txt
line: abc
line: def
line: 123 456
line:
答案 1 :(得分:1)
for files in
$(sed -n '/file/p' list.txt)
do
echo "${files}"
...
done
通常情况下,将命令绑定到循环的输出是错误的形式,但是sed通常可以可靠地执行,因为它总是引用整行。如果你希望它以与输入相同的形式输出,你必须确保在回显时在变量名周围加上双引号(“)。
答案 2 :(得分:1)
使用可能包含空格的变量时,必须引用它们以保留空格。这将起作用,例如:
for f in "$(cat fetch/list.txt)"; do # preserve spacing from $()
echo "$f" # preserve spacing from $f
done
另外几条建议:
$(...)
来反对`...`
,因为它可以更好地使用引号和嵌套。less
是一个交互式命令,如果您只想要文件内容,请使用cat
。但是直接循环文件内容会更有效(如Eric的回答中所述),而不是将文件转换为迭代的元素列表:
while read f; do # read each line into f
echo "$f"
done < fetch/list.txt # from fetch/list.txt
在这里,read
读取整行(而流程替换和反引号会生成项目列表,不一定是行,除非您引用它),因此在使用$f
时只需要引号。请注意<
输入重定向的位置:在done
关键字之后,这可能看起来令人困惑。
答案 3 :(得分:1)
这可能对您有用:
for file in "$(<list.txt)"; do echo "$file"; done
答案 4 :(得分:0)
一种可能的解决方案是将fetch/list.txt
提供给xargs
,并为文件中的每一行执行命令:
xargs -i sh -c 'echo "${1}" ; ...' _ {} < fetch/list.txt
一般来说,在shell脚本中应谨慎处理for f in [some list of values that might contain spaces]
。
答案 5 :(得分:-1)
这似乎有效:
list: all
for f in "`cat filename`"; \
do \
echo "$$f"; \
done
all:
/bin/true