为什么在传递到当前目录而不是路径时,Find会返回不同的排序结果?

人气:730 发布:2022-10-16 标签: shell zsh find ls

问题描述

我正在尝试编写一个Shell命令,返回最近修改的文件。 但是,该目录包含的文件超过了ls可以直接容纳的范围(因此使用find,我认为这是通过管道传输到其他命令的正确解决方案)。

在这样做的过程中,我遇到了在目录中运行find .和传递目录以查找(即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.pdfProfiles17_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 .find ~/Downloads而改变。

是怎么回事?我有一种模糊的直觉,这可能与我们正在查看inode的更改时间以及包含目录更改…有关一些东西。

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

推荐答案

xargs的工作是拆分超出系统可容纳范围的命令行。为了说明起见,我们假设您有四个文件和一个操作系统,其中ARG_MAX只有25个字节(尽管在现实生活中,它在现代系统上大约是MB)。然后在没有路径的情况下,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调用的最新文件。

在装有GNUfind(Linux等)的系统上,使用其-printf选项格式化修改时间在文件名之前的字符串。

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

我们按修改时间排序,然后丢弃修改时间,只打印文件名。空分隔符负责处理包含换行符的文件名;此功能尤其是GNU扩展名。

如果您没有GNU实用程序,可以将find -exec stat与类似的格式字符串一起使用;遗憾的是,stat的这一功能也没有标准化,但应该不难找到适用于BSD、MacOS等非Linux系统的示例。

404