先看结论
原因是
find
命令中的-exec
选项是逐个文件单独执行命令的。这种行为会导致每个命令独立处理每个文件,不能一次性对所有匹配的文件进行操作。因此类似find . -size +2k -exec ls -lhS {} \;
的命令并不会对已查找到的文件进行排序,因为查找到的文件单独执行了ls -lhS
命令(对每个文件单独执行相当于对自己和自己比较),并不是对所有文件进行比较而进行一次性排序。
详细证明
find
命令中的 -exec
选项是如何逐个执行命令的
在使用 find
命令查找符合条件的文件时,-exec
选项可以用来对每个匹配的文件执行一个指定的命令。为了更好地理解 -exec
选项的行为,我们可以通过以下示例和验证方法来证明 -exec
确实是逐个执行命令的。
示例文件准备
首先,我们在一个测试目录中创建几个示例文件:
mkdir -p ~/test
cd ~/test
dd if=/dev/zero of=file1 bs=1K count=4 # 4K 文件
dd if=/dev/zero of=file2 bs=1K count=6 # 6K 文件
dd if=/dev/zero of=file3 bs=1K count=10 # 10K 文件
dd if=/dev/zero of=file4 bs=1M count=1 # 1M 文件
dd if=/dev/zero of=file5 bs=1K count=2 # 2K 文件
使用 find
和 -exec
选项
运行以下命令:
find . -size +2k -exec ls -lhS {} \;
这条命令的作用是:
find . -size +2k
:找到所有大小大于2K的文件。-exec ls -lh {} \;
:对每个找到的文件执行ls -lhS
命令(按照文件大小排序)。
可以发现
ls -S
似乎并没有对查找到的文件进行大小排序,创建的时候是什么顺序,现在还是什么顺序***
证明 -exec
是逐个执行的
为了证明 -exec
选项是逐个执行的,使用 strace
工具来跟踪系统调用:
strace -f -o strace_output.txt find . -size +2k -exec ls -lh {} \;
在 strace_output.txt
文件中,查看每个 execve
调用:
grep execve strace_output.txt
我们看到以下的输出,每个文件对应一个 ls
命令的执行:
这恰恰说明,每个
ls -lh
命令是对每个文件单独执行的。(PID 分别为 12325, 12326, 12327, 12328
各自执行了 /bin/ls 命令,而不是一个进程执行)
使用时间戳验证
通过在 -exec
命令中插入时间戳来进一步验证每个命令的执行顺序:
find . -size +2k -exec sh -c 'echo $(date +%s%N) {}; ls -lh {}' \;
输每个文件的时间戳和文件信息:
可以看到,每个命令的时间戳是不同的,进一步证明了
-exec
是逐个文件执行命令的。
总结
通过上面的几种方法,我们可以明确地证明
find
命令中的-exec
选项是逐个文件单独执行命令的。这种行为会导致每个命令独立处理每个文件,不能一次性对所有匹配的文件进行操作,所以要用需要拿全部结果的进行操作的命令还是加一个管道符吧~