我需要逐行读取某个文本文件中的文件列表,然后将其翻译为-a filename1 -a filename2 -a filename3
的序列。
我试图这样做,但看起来设置FILES变量的语法在该上下文中是错误的:
files_pack:
@while read -r file; do \
FILES += "-a $$file"; \
done <$(LIST_FILE)
some_util $(FILES)
答案 0 :(得分:1)
外壳分配不能在=
/ +=
附近留出空格。
同样$(FILES)
将由make扩展。你想要"$${FILES[@]}"
。
我还修改了你的代码以使用数组而不是字符串,以便带有空格/等的文件。在名称中可以正常工作。
files_pack:
@while read -r file; do \
FILES+=(-a "$$file"); \
done <$(LIST_FILE)
some_util "$${FILES[@]}"
尽管如此,正如Jens所指出的那样,在许多系统上都不会使用/bin/sh
,并且需要告诉make使用/bin/bash
作为此目标的shell:
files_pack: SHELL := /bin/bash
或全球:
SHELL := /bin/bash
答案 1 :(得分:1)
如果LIST_FILE每行有一个文件,而您需要做的只是在-a
前面添加每行,那么您想要的是
files_pack:
some_util $$(sed 's/^/-a /' $(LIST_FILE))
答案 2 :(得分:1)
这也有效:
FILES=$(shell cat ${LIST_FILE)
FILES_OPT=$(addprefix -a,${FILES})
这个解决方案并不依赖于bash,适用于每个通用shell,并且不需要&#39; sed&#39;待安装。
答案 3 :(得分:1)
受Anton Kochkov's answer的启发,这是一个适用于任何shell的简单解决方案,但如果文件名包含空格或元字符则会失败:
files_pack:
some_util $(shell printf " -a %s" $$(cat $(FILES)))
这可以改进以处理具有除撇号之外的空格或特殊字符的文件名:
files_pack:
some_util $(shell IFS="$$(printf '\n+')"; IFS="$${IFS%+}"; printf " -a '%s'" $$(cat $(FILES)))
将IFS
设置为 newline + ,然后删除 + 的特殊顺序是唯一与Posix兼容的方式知道将IFS
设置为单个换行符,该换行符不涉及带有物理换行符的命令行。 (无论IFS
的设置如何,简单命令替换都会删除尾随换行符。)
使用bash,可以使用%q
printf格式(以及其他一些基本原理来简化)来简化并使其更加健壮:
files_pack: SHELL := /bin/bash
some_util $(shell IFS=$$'\n'; printf " -a %q" $$(<$(FILES)))