Makefile 多行命令在 Docker 中无法正常工作
Makefile multiline command does not work in Docker properly
我正在尝试从 Markdown 编译 HTML。我的 makefile
看起来像:
MD = pandoc \
--from markdown --standalone
# ...
$(MD_TARGETS):$(TARGET_DIR)/%.html: $(SOURCE_DIR)/%.md
mkdir -p $(@D); \
$(MD) --to html5 $< --output $@; \
sed -i '' -e '/href="./s/\.md/\.html/g' $@
当我在本地机器上 运行 一切正常时。
当我 运行 在 Docker 中相同时,我得到以下错误:
mkdir -p /project/docs; \
pandoc --from markdown --standalone --to html5 /project/source/changelog.md --output /project/docs/changelog.html; \
sed -i '' -e '/href="./s/\.md/\.html/g' /project/docs/changelog.html
sed: can't read : No such file or directory
makefile:85: recipe for target '/project/docs/changelog.html' failed
make: *** [/project/docs/changelog.html] Error 2
随后调用 make
给出了相同的错误,但使用了另一个文件:
sed: can't read : No such file or directory
makefile:85: recipe for target '/project/docs/todo.html' failed
显然,make 会在 HTML 完成之前以某种方式尝试 sed
。
但是我使用 make 的多行语法 ; \
以避免使用 subshell。
我也试过 && \
但它们都不起作用。我该怎么办?
不幸的是,您被您的 "obvious" 结论误导了 显然,在 HTML 完成之前以某种方式尝试 sed :) 这根本不是什么问题是。更仔细地查看您的错误消息:
sed: can't read : No such file or directory
注意can't read :
;那里应该有一个文件名。它应该说类似 can't read foobar:
的内容。很明显 sed
试图读取一个名为空字符串的文件。这是你的行 运行:
sed -i '' -e '/href="./s/\.md/\.html/g' /project/docs/changelog.html
这里明显的罪魁祸首是 -i
的空字符串参数。 sed 手册页将 -i
选项描述为:
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
请注意 (a) SUFFIX 是可选的,以及 (b) 参数及其选项之间没有 space。在您的示例中,您添加了 space,这导致 sed 认为未提供 SUFFIX 并将下一个参数 (''
) 视为文件名进行手术。
我不确定为什么当您从命令行 运行 它时它会起作用:我必须假设您的命令行版本不包含空字符串,否则它不包含space 在 -i
和 ''
之间。
使用其中之一:
sed -i'' -e '/href="./s/\.md/\.html/g' $@
或
sed --in-place= -e '/href="./s/\.md/\.html/g' $@
我正在尝试从 Markdown 编译 HTML。我的 makefile
看起来像:
MD = pandoc \
--from markdown --standalone
# ...
$(MD_TARGETS):$(TARGET_DIR)/%.html: $(SOURCE_DIR)/%.md
mkdir -p $(@D); \
$(MD) --to html5 $< --output $@; \
sed -i '' -e '/href="./s/\.md/\.html/g' $@
当我在本地机器上 运行 一切正常时。
当我 运行 在 Docker 中相同时,我得到以下错误:
mkdir -p /project/docs; \
pandoc --from markdown --standalone --to html5 /project/source/changelog.md --output /project/docs/changelog.html; \
sed -i '' -e '/href="./s/\.md/\.html/g' /project/docs/changelog.html
sed: can't read : No such file or directory
makefile:85: recipe for target '/project/docs/changelog.html' failed
make: *** [/project/docs/changelog.html] Error 2
随后调用 make
给出了相同的错误,但使用了另一个文件:
sed: can't read : No such file or directory
makefile:85: recipe for target '/project/docs/todo.html' failed
显然,make 会在 HTML 完成之前以某种方式尝试 sed
。
但是我使用 make 的多行语法 ; \
以避免使用 subshell。
我也试过 && \
但它们都不起作用。我该怎么办?
不幸的是,您被您的 "obvious" 结论误导了 显然,在 HTML 完成之前以某种方式尝试 sed :) 这根本不是什么问题是。更仔细地查看您的错误消息:
sed: can't read : No such file or directory
注意can't read :
;那里应该有一个文件名。它应该说类似 can't read foobar:
的内容。很明显 sed
试图读取一个名为空字符串的文件。这是你的行 运行:
sed -i '' -e '/href="./s/\.md/\.html/g' /project/docs/changelog.html
这里明显的罪魁祸首是 -i
的空字符串参数。 sed 手册页将 -i
选项描述为:
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
请注意 (a) SUFFIX 是可选的,以及 (b) 参数及其选项之间没有 space。在您的示例中,您添加了 space,这导致 sed 认为未提供 SUFFIX 并将下一个参数 (''
) 视为文件名进行手术。
我不确定为什么当您从命令行 运行 它时它会起作用:我必须假设您的命令行版本不包含空字符串,否则它不包含space 在 -i
和 ''
之间。
使用其中之一:
sed -i'' -e '/href="./s/\.md/\.html/g' $@
或
sed --in-place= -e '/href="./s/\.md/\.html/g' $@