xargs /bin/ls 和 exec ls 之间的区别?

xargs /bin/ls 和 exec ls 之间的区别?

嗨,这可能是一个新手问题,但为什么 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

  1. *你需要在第二个命令中引用find

  2. 这些/dev/fd/*设备与 、 等相对应stdinstdout这些stderr设备是模拟链接的,并且对于每个进程都是不同的,

  3. -type f,结果必须是常规文件,因此它们/dev/fd/*不在结果中,因为它们是块设备,

  4. 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 时存在。

相关内容