如何将ls命令输出存入Make变量并在后续流程中使用?
问题排查与解决
以下是导致pkgRelDate为空的常见原因及对应修复方案:
1. Make与Shell变量的转义错误
Make会先解析recipe里的所有$符号,再把内容传给Shell执行。如果你在recipe里定义的是Shell变量(比如DOWNLOAD_PATH=/tmp),那么Shell变量的引用必须用$$转义,否则Make会把$DOWNLOAD_PATH当成自己的变量解析,导致路径为空。
比如原代码里的${DOWNLOAD_PATH}如果是Shell变量,要改成$$DOWNLOAD_PATH;如果是Make变量,要确保它在Makefile里已经正确定义。
2. Awk语法兼容性问题
部分旧版本Awk(如BSD Awk)不支持match($0, /[0-9]{8}/, date)这种将匹配结果存入第三个参数的语法,会导致Awk无输出,最终pkgRelDate为空。
替换为兼容所有Awk版本的写法:
awk '{match($0, /[0-9]{8}/); print substr($0, RSTART, RLENGTH)}'
3. ls排序不可靠+路径不存在
ls | tail -n1依赖字典序和目录创建顺序一致,若目录命名规则变化会失效;且如果${DOWNLOAD_PATH}/${PROVIDER_NAME}路径不存在,ls会报错,后续命令无输出。- 建议先验证路径有效性,同时用数字排序确保拿到最新日期:
ls $(DOWNLOAD_PATH)/$(PROVIDER_NAME) | grep -E '[0-9]{8}' | sort -n | tail -n1
修正后的完整Recipe示例
# 定义Make变量(如果需要在多个recipe复用) DOWNLOAD_PATH = /tmp PROVIDER_NAME = tug.org TEMPLATE_NAME = your_template.txt # 目标规则 generate_pfl: @# 先验证路径是否存在 if [ ! -d "$(DOWNLOAD_PATH)/$(PROVIDER_NAME)" ]; then echo "Path not found!"; exit 1; fi; \ # 获取最新日期 pkgRelDate=$$(ls $(DOWNLOAD_PATH)/$(PROVIDER_NAME) | grep -E '[0-9]{8}' | awk '{match($0, /[0-9]{8}/); print substr($0, RSTART, RLENGTH)}' | sort -n | tail -n1); \ # 调试用:打印变量值 echo "Latest release date: $$pkgRelDate"; \ # 生成目标文件 cat $(TEMPLATE_NAME) > "$$pkgRelDate.pfl"
额外调试技巧
在recipe里加入set -x可以开启Shell调试模式,看到每一步的执行细节,方便定位哪里出问题:
generate_pfl: @set -x; \ DOWNLOAD_PATH=/tmp; \ PROVIDER_NAME=tug.org; \ pkgRelDate=$$(ls $$DOWNLOAD_PATH/$$PROVIDER_NAME | ...); \ ...
内容的提问来源于stack exchange,提问作者Thesevs SCUTULATUS
相关产品推荐
相关产品推荐

