Mar*_*ter 5 ls find xargs sort
我想列出所有/usr/
使用ls
. 我不是ls
直接打电话,而是通过xargs
. 此外,我正在使用xargs
参数-L
并-P
利用我的所有内核。
find /usr/ -type f -print0 | xargs -0 -L16 -P4 ls -lAd | sort -k9 > /tmp/aaa
Run Code Online (Sandbox Code Playgroud)
上面的命令按预期工作。它产生不错的输出。但是,当我将行-L
数参数从 16 增加到 64 时:
find /usr/ -type f -print0 | xargs -0 -L64 -P4 ls -lAd | sort -k9 > /tmp/bbb
Run Code Online (Sandbox Code Playgroud)
结果输出都是乱码。我的意思是,输出不再从新行开始,新行从“上一个”行的中间开始并且都混在一起:
-rw-r--r-- 1 root root 5455 Nov 16 2010 /usr/shareonts/X11/encodings/armscii-8.enc.gz
-rw-r--r-- 1 root root 1285 May 29 2016-rw-r--r-- 1 root root 6205 May 29 2016 /usr/include/arpa/nameser_compat.h
-rw-r--r-- 1 root root 0 Apr 17 20-rw-r--r-- 1 root root 933 Apr 16 2012 /usr/share/icons/nuoveXT2/16x16/actions/address-book-new.png
-rw-r--r-- 1 root root 53651 Jun 17 2012-rw-r--r-- 1 root root 7117 May 29 2016 /usr/include/dlfcn.h
-rw-r--r-- 1 root root 311 Jun 9 2015-rw-r--r-- 1 root root 1700 Jun 9 2015 /usr/share/cups/templates/de/add-printer.tmpl
-rw-r--r-- 1 root root 5157 M1 root root 10620 Jun 14 2012 /usr/lib/perl5/Tk/pTk/tkIntXlibDecls.m
-rw-r--r-- 1 root -rwxr-xr-x 1 root root 1829 Jan 22 2013 /usr/lib/emacsen-common/packages/install/dictionaries-common
-rw-r--r-- 1 root r-rw-r--r-- 1 root root 1890 Jun 2 2012 /usr/share/perl5/Date/Manip/TZ/afaddi00.pm
-rw-r--r-- 1 root root 1104 Jul-rw-r--r-- 1 root root 10268 Jul 27 15:58 /usr/share/perl/5.14.2/B/Debug.pm
-rw-r--r-- 1 root root 725 Apr 1-rw-r--r-- 1 root root 883 Apr 1 2012 /usr/share/icons/gnome/16x16/actions/address-book-new.png
Run Code Online (Sandbox Code Playgroud)
有趣的是,它只在使用-L64
或更大时发生。我没有看到这个问题-L16
。
有人能解释一下这里发生了什么吗?
这与写入管道有关。随着-L16
您运行的是每个16个文件的一个过程,这会产生大约一千个字符,这取决于文件名有多长。和-L64
你在一起大约有四千。该ls
程序几乎可以肯定使用stdio库,并且几乎可以肯定使用4kB缓冲区进行输出以减少写入调用的次数。
所以 find 产生了大量的文件名,然后(对于 -L64 的情况) xargs 将它们分成 64 个包并启动 4 个ls
进程来处理它们。每个ls
将生成它的第一个 4k 输出并将其写入管道进行排序。请注意,此 4k 通常不会以换行符结尾。所以说第三个ls
首先准备好它的第一个 4kB,然后它结束
lrwxrwxrwx 1 root root 6 Oct 21 2013 bzegrep -> bzgrep
-rwxr-xr-x 1 root root 4877 Oct 21 2013 bzexe
lrwxrwxrwx 1 root root 6 Oct 2
Run Code Online (Sandbox Code Playgroud)
然后第一个 ls 输出一些东西,例如
total 123459
Run Code Online (Sandbox Code Playgroud)
那么排序的输入将包括 lrwxrwxrwx 1 root root 6 Oct 2total 123459
在这种-L16
情况下,ls
进程(通常)只会一次性输出一组完整的结果。
当然,对于这种情况,您使用 xargs 和 ls 只是在浪费时间和资源,您应该只find
输出它已有的信息,而不是运行额外的程序来再次发现信息。