Kus*_*nda 11 posix timestamps files test
内置test
和[
实用程序在大多数 shell 中都有-nt
("newer than") 和-ot
("older than") 测试,即使 shell 以“POSIX 模式”运行(对于同名的外部实用程序也是如此)我可以访问的系统)。这些测试用于比较两个文件的修改时间戳。它们记录的语义在不同的实现中略有不同(关于如果一个或另一个文件不存在会发生什么),但它们未包含在POSIX 规范中。为test
实用程序。
他们不结转到
test
时,从[KornShell]壳去除有条件的命令,因为他们没有被列入工具test
内置于历史实现实用sh
工具。
假设我想比较/bin/sh
shell 脚本中文件之间的修改时间戳,然后根据一个文件是否比另一个文件新来采取行动,如
if [ "$sigfile" -nt "$timestamp" ] ||
[ "$sigfile.tmp" -nt "$timestamp" ]
then
return
fi
Run Code Online (Sandbox Code Playgroud)
...除了make
(至少可以说脚本的其余部分变得笨拙)之外,我还可以使用什么其他实用程序?或者我应该假设没有人会在“历史实现sh
”上运行脚本,或者辞职为特定的shell编写,例如bash
?
cuo*_*glm 13
POSIXLY:
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
Run Code Online (Sandbox Code Playgroud)
使用文件的绝对路径可防止文件名仅包含换行符的误报。
如果使用相对路径,则将find
命令更改为:
find -L "$f1" -prune -newer "$f2" -exec echo . \;
Run Code Online (Sandbox Code Playgroud)
这可能是使用最古老的 Unix 命令之一的情况,ls
.
x=$(ls -tdL -- "$a" "$b")
[ "$x" = "$a
$b" ]
Run Code Online (Sandbox Code Playgroud)
如果 a 比 b 新,则结果为真。
您提出了一个有趣的问题并提出了一个应该首先得到验证的主张。
我检查了以下行为:
$shell -c '[ Makefile -nt SCCS/s.Makefile ] && echo newer'
Run Code Online (Sandbox Code Playgroud)
与各种贝壳。结果如下:
bash不起作用 - 不打印任何内容。
波什 作品
dash不起作用 - 不打印任何内容。
ksh88不起作用 - 不打印任何内容。
ksh93 工作原理
mksh不起作用 - 不打印任何内容。
posh打印: posh: [: -nt: 意外的运算符/操作数
亚什 作品
zsh 在较新版本中工作,较旧版本不打印任何内容
因此,九个 shell 中有四个支持-nt功能并正确实现它。在这种情况下,正确意味着:能够比较支持亚秒时间戳粒度的最新平台上的时间戳。请注意,我选择的文件的时间戳通常仅存在几微秒的差异。
由于更容易找到有效的find
实现,我建议替换
if [ "$file1" -nt "$file2" ] ; then
echo newer
fi
Run Code Online (Sandbox Code Playgroud)
通过find
基于表达式。
if [ "$( find "$file1" -newer "$file2" )" ]; then
echo newer
fi
Run Code Online (Sandbox Code Playgroud)
至少只要$file1
不包含换行符就可以工作。
if [ "$( find -L "$file1" -newer "$file2" -exec echo newer \; )" ]; then
echo newer
fi
Run Code Online (Sandbox Code Playgroud)
有点慢但工作正常。
顺便说一句:关于 make,我不能代表所有 make 实现,但SunPro Make
支持与纳秒粒度的时间比较,因为大约。20 年过去了,最近smake
又gmake
添加了这个功能。