嗨,这可能是一个新手问题,但为什么 xargs /bin/ls 在这种情况下不起作用?我以为它应该更快?还有那些 /fd/3 目录是什么?
sh-3.2# find / -name 'GOALS*' -exec ls -l {} \;
find: /dev/fd/3: Not a directory
find: /dev/fd/4: Not a directory
.... This returns me the expected result....
但是这将返回目录中的完整文件列表
sh-3.2# find / -name GOALS* -type f | xargs /bin/ls -l
我在使用 MacOS。
答案1
*
你需要在第二个命令中引用find
,这些
/dev/fd/*
设备与 、 等相对应stdin
。stdout
这些stderr
设备是模拟链接的,并且对于每个进程都是不同的,说
-type f
,结果必须是常规文件,因此它们/dev/fd/*
不在结果中,因为它们是块设备,xargs ls -l
和你的一样...ls -l {}
我甚至怀疑在这种情况下性能会更好,但xargs
它更聪明,而且有理由使用它,例如正确处理里面有空格的文件,
如果你正在调试你的第二个版本find
,首先查看不包含该| xargs ls -l
部分的输出
答案2
第一个命令会ls
针对与您提供的名称匹配的每个文件名执行一条新命令。这包括目录、符号链接、设备以及可以找到的任何其他内容。ls
找到文件后,命令就会执行,因此找到文件后,您会看到列表。
第二条命令仅匹配具有指定名称的文件。由于您没有引用GOALS*
,因此如果您从具有匹配条目的目录运行,它将替换GOALS*
命令中的条目。 xargs
调用ls
将是一个很长的文件名列表。直到 find 完成或找到足够长的匹配列表,您才会看到结果。由于解析规则,包含空格的文件名会导致问题。
对于名称中没有空格的文件,这三个命令应该是等效的。第三个选项并不适用于所有操作系统,但可以处理名称中的空格。
find / -name 'GOALS*' -type f -exec ls -l {} \;
find / -name 'GOALS*' -type f | xargs /bin/ls -l
find / -name 'GOALS*' -type f -print0 | xargs -0 /bin/ls -l
答案3
shell (bash) 内置命令exec
用给定的参数替换当前 shell。例如,尝试 exec sleep 1。可执行文件xargs
是 GNU findutils 包的一部分。它将执行作为第一个参数提供给它的命令,并从标准输入读取参数。
例如:
$ echo -e "小牛喝牛奶\n人们吃牛" | xargs -L1 cowsay ___________________ < 小牛喝奶 > ------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || _________________ < 人吃牛 > ----------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
您提供的示例“不起作用”,因为由计算机上的所有文件以及 /sys 和 /proc 下的特殊文件组成的参数列表变得太大。您不能要求命令处理任意大的参数列表,因为存在限制(getconf ARG_MAX -- 字节,我认为)。
有时,您确实想使用大量参数列表来执行某些操作,而解决方案是处理列表的块而不是一次处理整个列表。
例如:
$ cat tmp/moo.sh /bin/sh #!/bin/sh 复制代码 echo 处理 $# 参数 $ seq 0 10000 | xargs -L 1001 sh tmp/moo.sh | cat -n 1 处理 1001 个参数 2 处理 1001 个参数 3 处理1001个参数 4 处理1001个参数 5 处理1001个参数 6 处理1001个参数 7 处理1001个参数 8 处理 1001 个参数 9 处理1001个参数 10 处理 992 个参数
关于“那些 fd”文件夹的问题的最后一部分是关于F伊莱d描述符。运行 find 时,它会查看 /proc 并查看正在运行的进程的文件描述符(标准输入、标准输出、用于读写的常规文件)。当 find 退出并且 xargs 接管时,其中一些进程可能已不复存在。因此会出现错误。/dev/fd 中的文件实际上只是符号链接:
$ ll /dev/fd/ 共 0 lrwx------ 1 jaroslav jaroslav 64 11月18日 01:57 0 -> /dev/pts/7 lrwx------ 1 jaroslav jaroslav 64 11月18日 01:57 1 -> /dev/pts/7 lrwx------ 1 jaroslav jaroslav 64 11月18日 01:57 2 -> /dev/pts/7 lr-x------ 1 jaroslav jaroslav 64 11月 18日 01:57 3 -> /proc/21677/fd 哎呀:〜 $ 文件 /dev/pts/7 /dev/pts/7:特殊字符 哎呀:〜 $ sudo echo "MOOOOOOO" >> /dev/pts/7 密码: 哞哞
我所做的就是将进程写入终端的标准输出。我不知道进程 21677 是什么,但到find /
完成时,我确信它将被销毁,即使它在 find 扫描 /proc 时存在。