首页 > 解决方案 > 为什么 find 在传递当前目录与路径时返回不同的排序结果?

问题描述

我正在尝试编写一个返回最近修改的文件的 shell 命令。但是,该目录包含的文件比ls直接容纳的文件多(因此使用find,我理解这是管道到其他命令的正确解决方案)。

这样做时,我遇到了find .在目录中运行和将目录传递给 find ( ie find $folder ) 之间令人困惑的区别。

这是一个例子:

➜  echo $SHELL
/usr/local/bin/zsh
➜  pwd
/Users/aresnick/Downloads
➜  find . -type f -maxdepth 1 -print0 | xargs -0 ls -t | head -1
./DID_Codebook_2020.pdf
➜  find $(pwd) -type f -maxdepth 1 -print0 | xargs -0 ls -t | head -1
/Users/aresnick/Downloads/Profiles17_MA.pdf
➜  find /Users/aresnick/Downloads -type f -maxdepth 1 -print0 | xargs -0 ls -t | head -1
/Users/aresnick/Downloads/Profiles17_MA.pdf

请注意,DID_Codebook_2020.pdf该文件与Profiles17_MA.pdf. 我如何解释为什么这些命令似乎返回不同的结果?

作为参考,这里是ls -halt | head -5目录中的输出(包括这里混淆的两个最新文件)。

➜ ls -halt | head -5
total 51229416
drwxr-xr-x+   92 aresnick  staff   2.9K Oct 12 10:34 ..
drwx------@ 4033 aresnick  staff   126K Oct 12 10:02 .
-rw-r--r--@    1 aresnick  staff   1.7M Oct 12 10:02 DID_Codebook_2020.pdf
-rw-r--r--@    1 aresnick  staff   470K Oct 12 10:00 Profiles17_MA.pdf

通过 更仔细地观察stat,似乎更改时间实际上是更新的Profiles17_MA.pdf

➜  stat -f "ACCESS-%Sa   CHANGE-%Sc %SN" {DID_Codebook_2020.pdf,Profiles17_MA.pdf}
ACCESS-Oct 12 10:02:14 2020   CHANGE-Oct 12 10:02:08 2020 DID_Codebook_2020.pdf
ACCESS-Oct 12 10:02:14 2020   CHANGE-Oct 12 10:02:10 2020 Profiles17_MA.pdf

但是,我不明白这如何解释为什么排序顺序会随着find .vs.改变find ~/Downloads

是什么赋予了? 我有一种模糊的直觉,这可能与我们正在查看 inode 的更改时间这一事实有关,以及与包括目录更改有关的某些东西……某些东西。

提前致谢!请注意,虽然我也对特定排序问题的解决方案感兴趣,但我最感兴趣的是了解为什么会出现差异。

标签: shellfindzshls

解决方案


的工作xargs是拆分超过系统可以容纳的命令行。让我们假设您有四个文件和一个ARG_MAX只有 25 个字节的操作系统(尽管在现实生活中它在现代系统上大约为兆字节)。然后没有路径,xargs运行

ls -t ./a ./b ./c ./d

但是对于完整路径,必须将命令行拆分为两个调用,以免超过命令行长度的限制:

ls -t /path/to/a /path/to/b
ls -t /path/to/c /path/to/d

当然,如果d是您的最新文件,head则仍然会从第一次ls调用中返回最新文件。

在具有 GNU find(Linux 等)的系统上,使用它的-printf选项来格式化一个字符串,其中修改时间在文件名之前。

find . -type f -printf "%T+\t%p\0" |
sort -rnz |
perl -n000 's/^[^\t]+\t//; print; exit'

我们按修改时间排序,然后丢弃修改时间,只打印文件名。空分隔符负责处理带有换行符的文件名;这个特性尤其是一个 GNU 扩展。

如果您没有 GNU 实用程序,您可以使用find -exec stat类似的格式字符串;不幸的是,这个特性stat也不是标准化的,但是应该不难找到非 Linux 系统的例子,比如 BSD、macOS 等。


推荐阅读