内置test
和[
实用程序在大多数 shell 中都具有-nt
(“更新于”)和-ot
(“旧于”)测试,即使 shell 在“POSIX 模式”下运行(对于外部同名实用程序也是如此)我有权访问的系统)。这些测试用于比较两个文件的修改时间戳。它们记录的语义在不同的实现中略有不同(关于如果一个或另一个文件存在或不存在时会发生什么),但它们不包含在POSIX 规范。对于test
公用事业。
当条件命令从 [KornShell] shell 中删除时,它们不会被转移到
test
实用程序中,因为它们尚未包含在test
实用程序历史实现中内置的实用程序中sh
。
假设我想比较/bin/sh
shell 脚本中文件之间的修改时间戳,然后根据一个文件是否比另一个文件新来采取行动,如下所示
if [ "$sigfile" -nt "$timestamp" ] ||
[ "$sigfile.tmp" -nt "$timestamp" ]
then
return
fi
...除了make
(至少可以说这会使脚本的其余部分变得难以处理)之外,我还可以使用什么其他实用程序?或者我应该假设没有人会在“历史实现sh
”上运行脚本,或者放弃为一个具体的外壳像bash
?
答案1
正面:
f1=/path/to/file_1
f2=/path/to/file_2
if [ -n "$(find -L "$f1" -prune -newer "$f2")" ]; then
printf '%s is newer than %s\n' "$f1" "$f2"
fi
使用文件的绝对路径可以防止文件名仅包含换行符的误报。
如果使用相对路径,则将find
命令更改为:
find -L "$f1" -prune -newer "$f2" -exec echo . \;
答案2
这可能是使用最古老的 Unix 命令之一的情况ls
。
x=$(ls -tdL -- "$a" "$b")
[ "$x" = "$a
$b" ]
如果 a 比 b 新,则结果为 true。
答案3
您提出了一个有趣的问题并提出了一个应该首先得到验证的主张。
我检查了以下行为:
$shell -c '[ Makefile -nt SCCS/s.Makefile ] && echo newer'
与各种贝壳。结果如下:
巴什不起作用 - 不打印任何内容。
波什 作品
短跑不起作用 - 不打印任何内容。
克什88不起作用 - 不打印任何内容。
克什93 作品
姆克什不起作用 - 不打印任何内容。
豪华打印: posh: [: -nt: 意外的运算符/操作数
亚什 作品
桀骜 适用于较新的版本,旧版本不打印任何内容
所以九个壳中有四个支持-nt功能并正确实施。在这种情况下正确意味着:能够比较支持亚秒级时间戳粒度的最新平台上的时间戳。请注意,我选择的文件的时间戳通常仅存在几微秒的差异。
由于更容易找到有效的find
实现,我建议替换
if [ "$file1" -nt "$file2" ] ; then
echo newer
fi
通过find
基于表达式。
if [ "$( find "$file1" -newer "$file2" )" ]; then
echo newer
fi
至少只要$file1
不包含换行符就可以工作。
if [ "$( find -L "$file1" -newer "$file2" -exec echo newer \; )" ]; then
echo newer
fi
有点慢但工作正常。
顺便提一句:关于品牌我不能代表所有 make 实现,但SunPro Make
支持与纳秒粒度的时间比较,因为大约。 20 年过去了,最近smake
又gmake
添加了这个功能。