如何在 bash 中测试两个符号链接哪个更旧(或更新)

如何在 bash 中测试两个符号链接哪个更旧(或更新)

显然,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如果f1f2目录)。

如果该对命令中的每个命令都是静默的,那么意味着这两个文件相应的时间同样长(或者不幸的是,至少一个 mtime 在此期间被修改了)。

在每种情况下,退出状态都将是0(除非发生某些严重错误,例如其中一个文件不存在)。这意味着您不能简单地使用退出状态,find就像使用退出状态或[一样[[

请记住,如果测试成功,您可以-exec在末尾添加来执行某些操作。或者,如果命令不是静默的,您可以通过 进行管道传输来测试,并从 中获取退出状态。find-newergrep -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

相关内容