You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Makefile遍历子文件夹批量构建Docker镜像时命令展开异常问题

批量构建Docker镜像的Makefile问题解决

问题描述

我有一个包含未知数量子文件夹的父文件夹,每个子文件夹中都包含一个Dockerfile。我希望编写一条Makefile命令,批量构建以子文件夹名称命名并对应打标签的镜像。

我先做了简单测试:

build.all.images:
    for f in $(find $(image_folder) -type d -maxdepth 1 -mindepth 1 -exec basename {} \;); do echo $${f}; done

当我将image_folder的值硬编码后单独执行find命令时,子文件夹被成功列出。但运行make命令时,仅得到如下输出:

for f in ; do echo ${f}; done

我还尝试使用ls命令结合tr、cut来获取子文件夹列表,但结果相同:

build.all.images:
    for f in $(ls -l $(image_folder) | grep '^d' | tr -s ' ' | cut -d ' ' -f 9); do echo $${f}; done

错误原因

问题出在Make的变量/函数展开时机:
Make会在执行shell命令之前,先解析所有$(...)语法。你写的$(find ...)和$(ls ...)会被Make当成自己的函数调用,但Make并没有内置find或ls函数,所以解析后返回空字符串,最终shell执行的就是空循环。

解决方案

有两种常用的修复方式:

方式1:使用Make内置的wildcard函数获取子目录

Make的wildcard函数可以直接匹配目录,避免调用shell命令:

# 定义父文件夹路径
image_folder := ./your-parent-folder

build.all.images:
	for f in $(wildcard $(image_folder)/*/); do \
		# 去掉路径末尾的斜杠,得到子文件夹名称
		img_name=$$(basename $$f); \
		# 构建镜像,标签为子文件夹名称
		docker build -t $$img_name $(image_folder)/$$img_name; \
	done

方式2:转义shell命令中的$符号

把shell命令里的$(...)改为$$(...),让Make把$$解析为单个$传递给shell执行:

image_folder := ./your-parent-folder

build.all.images:
	for f in $$(find $(image_folder) -type d -maxdepth 1 -mindepth 1 -exec basename {} \;); do \
		echo $$f; \
		docker build -t $$f $(image_folder)/$$f; \
	done

注意:Makefile中多行shell命令需要用\换行,并且每行开头的缩进必须是Tab键(不能用空格)。

内容的提问来源于stack exchange,提问作者Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 15:40:41