make中的Shell状态代码

Ome*_*Zak 18 shell makefile

我使用Makefile(在Linux下运行GNU make)来重构Python脚本时自动完成我的工作.该脚本创建了一个输出文件,我想确保输出文件在我的重构中保持不变.

但是,我发现无法获取命令的状态代码以影响后续shell if命令.

以下规则说明了问题:

check-cond-codes:
    diff report2008_4.csv report2008_4.csv-save-for-regression-testing; echo no differences: =$$!=
    diff -q poalim report2008_4.csv; echo differences: =$$!=
Run Code Online (Sandbox Code Playgroud)

第一个'diff'比较两个相同的文件,第二个比较两个不同的文件.输出是:

diff report2008_4.csv report2008_4.csv-save-for-regression-testing; echo no differences: =$!=
no differences: ==
diff -q poalim report2008_4.csv; echo differences: =$!=
Files poalim and report2008_4.csv differ
differences: ==
Run Code Online (Sandbox Code Playgroud)

显然'$$!' 是捕获'diff'状态代码的错误变量.即使在Makefile开头使用SHELL:=/bin/bash也无法解决问题.

返回我需要的值的变量(如果它存在的话)将在真实规则中的'if'命令中使用.

创建一个小的ad-hoc shell脚本代替在Makefile中内联编写所有命令的替代方案是不可取的,但我会将它作为最后的手段使用它.

有关:

Eri*_*ski 37

我想你正在寻找$?shell变量,它给出了上一个命令的退出代码.例如:

$ diff foo.txt foo.txt
$ echo $?
0
Run Code Online (Sandbox Code Playgroud)

要在makefile中使用它,你必须转义$,如$$?:

all:
    diff foo.txt foo.txt ; if [ $$? -eq 0 ] ; then echo "no differences" ; fi
Run Code Online (Sandbox Code Playgroud)

请注意,make中规则主体中的每个命令都在一个单独的子shell中运行.例如,以下内容不起作用:

all:
    diff foo.txt foo.txt
    if [ $$? -eq 0 ] ; then echo "no differences" ; fi
Run Code Online (Sandbox Code Playgroud)

因为diffif命令是在不同的shell进程中执行的.如果要使用命令的输出状态,则必须在同一shell的上下文中执行此操作,如在前面的示例中所示.

  • 简单`diff foo.txt foo.txt && echo"没有差异"`看起来更苗条:) (2认同)

Ome*_*Zak 4

使用“$$?” 而不是“$$!” (感谢基于进程退出代码的退出Shell脚本的第4个答案)