1

我的一部分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

有谁知道让每一行都被完全阅读,而不管空格?

4

6 回答 6

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: 
于 2013-11-09T23:37:33.073 回答
1
for files in
$(sed -n '/file/p' list.txt)
do
echo "${files}"
...
done

通常,将命令绑定到循环的输出是不好的形式,但 sed 通常可以可靠地做到这一点,因为它总是引用整行。如果您希望它以与输入相同的形式输出,则必须确保在回显时在变量名称周围加上双引号 (")。

于 2013-11-09T23:32:43.523 回答
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关键字之后,这可能看起来很混乱。

于 2013-11-10T00:14:12.770 回答
1

这可能对您有用:

for file in "$(<list.txt)"; do echo "$file"; done
于 2013-11-10T07:49:56.960 回答
0

一种可能的解决方案是为文件中的每一行fetch/list.txt提供xargs并执行您的命令:

xargs -i sh -c 'echo "${1}" ; ...' _ {} < fetch/list.txt

通常for f in [some list of values that might contain spaces],在 shell 脚本中应谨慎处理。

于 2013-11-09T23:27:26.540 回答
-1

这似乎有效:

list:          all
    for f in "`cat filename`"; \
    do \
        echo "$$f"; \
    done

all:
    /bin/true
于 2013-11-09T23:33:44.253 回答