makefile 如何检测本地计算机中是否有命令可用?

Fed*_*nez 12 shell make hashsum

我开始使用org-modeGTD风格的系统中规划我的任务。将每个 org 文件放在Dropbox文件夹的目录中,我运行 emacs 来编辑/管理来自三个不同本地机器的这些文件:Cygwin、Mac OS X 和 Debian。由于我还使用MobileOrg从我的 iPad 访问这些组织文件,因此checksums.dat在进行任何更改时,文件必须保持最新。这可以通过运行来完成md5sum *.org > checksums.dat

问题是命令有三种不同的md5sum命令:md5sum.exe在 Cygwin、md5Mac OS X 和md5sumDebian 中。最理想的情况是生成文件,存储在 Dropbox 文件中,检测当前机器中可用的命令并运行该命令来执行 md5 校验和操作。

Gil*_*il' 8

生成校验和的可能命令

不幸的是,没有生成加密校验和的标准实用程序。有一个标准工具来生成一个CRC:cksum; 这可能足以用于检测非敌对环境中的变化。

我建议使用 SHA1 而不是 MD5。有 MD5 实用程序但没有 SHA1 的系统并不多,如果您打算使用加密校验和,您不妨使用一种没有已知方法的算法来查找冲突(假设您还检查了大小)。

一种非标准但常见且可以计算摘要的工具是OpenSSL。它可用于 Cygwin、Debian 和 OSX,但不幸的是,它不是 OSX 上默认安装的一部分。

openssl dgst -sha1
Run Code Online (Sandbox Code Playgroud)

在 OSX 10.6 上,有一个shasum实用程序,它也存在于 Debian(它是perl软件包的一部分)上,我也相信 Cygwin。这是一个 Perl 脚本。大多数 unix 系统都安装了 Perl,因此如果您担心此脚本无法在任何地方使用,您可以将该脚本与您的 makefile 捆绑在一起。

为您的系统选择正确的命令

好吧,假设您真的找不到适用于任何地方的命令。

在壳中

使用type内置命令查看命令是否可用。

sum=
for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do
  if type "${x%% *}" >/dev/null 2>/dev/null; then sum=$x; break; fi
done
if [ -z "$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi
$sum *.org
Run Code Online (Sandbox Code Playgroud)

GNU 制造

您可以使用该shell函数在加载生成文件时运行 shell 代码段并将输出存储在变量中。

sum := $(shell { command -v sha1sum || command -v sha1 || command -v shasum; } 2>/dev/null)
%.sum: %
        $(sum) $< >$@
Run Code Online (Sandbox Code Playgroud)

便携式 (POSIX) 制造

您只能在规则中运行 shell 命令,因此计算校验和的每个规则都必须包含查找代码。您可以将代码片段放在一个变量中。请记住,规则中的单独行是独立评估的。还要记住,$要传递给 shell 的符号需要转义为$$.

determine_sum = \
        sum=; \
        for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do \
          if type "$${x%% *}" >/dev/null 2>/dev/null; then sum=$$x; break; fi; \
        done; \
        if [ -z "$$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi

checksums.dat: FORCE
    $(determine_sum); \
    $$sum *.org
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 5

这有点像 hack,但是您可以测试每个是否存在并在它们存在时执行它们:

[ -x "`which md5 2>/dev/null`" ] && md5 newfile >>sums
[ -x "`which md5sum 2>/dev/null`" ] && md5sum newfile >>sums
Run Code Online (Sandbox Code Playgroud)

我很确定 cygwin 可以识别md5sum不带 的命令(包括).exe,但如果必须,请包括它。

  • `which` 退出值不可移植。使用 `type` 代替(你可能想使用 `if; then; elif` 以避免在有多个可执行文件时出现问题)。`which` 和 `type` 无论如何只查找可执行文件,因此您使用 -x 的测试毫无意义。 (4认同)