显然,bash 测试-nt
并-ot
取消引用链接。
让我们考虑以下文件及其链接:
$ ls -lt --full-time f* | cut -d ' ' -f 6-
2023-04-24 02:05:01.083919712 +0200 f1l -> f1
2023-04-24 02:04:56.667857553 +0200 f2l -> f2
2023-04-24 02:04:41.667646860 +0200 f2
2023-04-24 02:04:38.947608730 +0200 f1
如您所见,f1 比 f2 旧,而 f2 又比 f2l 旧,而 f2l 又比 f1l 旧。但是,bash 并不这么认为,因此取消了对符号链接的引用:
$ if [[ f1l -ot f2l ]]; then echo "f1l is older than f2l"; fi
f1l is older than f2l
$ if [[ f2l -nt f1l ]]; then echo "f2l is newer than f1l"; fi
f2l is newer than f1l
在 bash 中,如何以编程方式测试两个给定符号链接中哪一个更旧?我们希望比较链接本身的日期和时间,而不是引用文件的日期和时间。(如果有帮助,您可以假设 ext4 文件系统。)测试应该为我们提供一个返回值,以便我们可以编写如下内容(对于尚未确定的is_older $1 $2
):
if is_older $1 $2 then echo "$1 is older than $2"; fi
答案1
find
默认情况下不取消引用链接,其-newer
主要测试mtimes:
find f1l -newer f2l # will "find" f1l
find f2l -newer f1l # will be silent
f1
与您的f2
结果将相反:
find f1 -prune -newer f2 # will be silent
find f2 -prune -newer f1 # will "find" f2
(-prune
如果f1
是f2
目录)。
如果该对命令中的每个命令都是静默的,那么意味着这两个文件相应的时间同样长(或者不幸的是,至少一个 mtime 在此期间被修改了)。
在每种情况下,退出状态都将是0
(除非发生某些严重错误,例如其中一个文件不存在)。这意味着您不能简单地使用退出状态,find
就像使用退出状态或[
一样[[
。
请记住,如果测试成功,您可以-exec
在末尾添加来执行某些操作。或者,如果命令不是静默的,您可以通过 进行管道传输来测试,并从 中获取退出状态。find
-newer
grep -q .
grep
find f1l -newer f2l | grep -q . && echo 'f1l is newer'
find f2l -newer f1l | grep -q . && echo 'f2l is newer'
之前的部分&&
(即find … | grep …
)通过其退出状态返回成功/失败,因此它可以用在您想要使用[
或 的地方[[
。请注意:其退出状态有grep --quiet
错误吗?
注意grep -q .
,如果测试的文件名仅包含换行符,则不会检测到我们想要的内容;但是在这里,您知道确切的文件名,并且它们不是这样的。如果它们可以像这样,那么您应该按以下方式修复命令:
find "$file1" -prune -newer "$file2" -exec echo a \; | grep -q a && printf '%s\n' "$file1 is newer"
上述命令是通用的,而且非常强大(它可以处理带有换行符、空格以及路径名中允许的任何内容的路径名)。如果您find
支持-printf
(GNUfind
支持),那么您可能需要-printf 'a\n'
而不是-exec echo a \;
,特别是如果您要find
多次调用。-exec echo
调用外部可执行文件,-printf
由其内部处理find
。