什么时候应该使用 subshel​​l 和 `xargs`?

han*_*rak 8 command-line shell xargs conventions subshell

许多简单的命令 usingxargs可以重写为使用子外壳的命令。例如,这是我今天早些时候使用的东西,用于连接 中的 10 个最大的二进制文件/usr/bin,使用 subshel​​l 与 xargs 编写:

子外壳:

$ cat $(du -sh /usr/bin/* | sort -h | tail | cut -d "      " -f 2 | tr "\n" " ")
Run Code Online (Sandbox Code Playgroud)

xargs

$ du -sh /usr/bin/* | sort -h | tail | cut -d "      " -f 2 | tr "\n" " " | xargs cat
Run Code Online (Sandbox Code Playgroud)

那么什么时候应该使用子shell,什么时候应该使用xargs

笔记:

cut 的分隔符是一个硬制表符,显然在 SE 上无法正确显示。

slm*_*slm 8

这是一个有点自以为是的问题,但我只想说,它高度依赖于两件事:

  1. 你要运行的命令是什么?
  2. 您要运行多少个实例?

如果您可能运行数十到数百个相同的过程,那么xargs最有意义。此外,如果这些流程的启动成本很高,xargs这可能是最好的选择。

但是,如果只有少数命令实例,那么在子 shell 中运行它们就可以了。

如果子shell 生成的参数长度非常长,那么您需要使用xargs. 但是这个限制非常极端,通常是 2MB-4MB 的字符,所以你不太可能超过它。你可以这样检查:

$ xargs --show-limits < /dev/null
Your environment variables take up 4805 bytes
POSIX upper limit on argument length (this system): 2090299
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2085494
Size of command buffer we are actually using: 131072
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这些命令似乎都不起作用。该cut -d " " -f2是无效的,cut只能取一个字符作为分隔符。试试这个:

$ du -sh /usr/bin/* | sort -h | awk 'NR<=10 {print $2}' | tr "\n" " "
-or-
$ du -sh /usr/bin/* | sort -h | tail | cut -f2- | tr "\n" " "
Run Code Online (Sandbox Code Playgroud)

awk如果您有任何带有空格的文件名或目录,在此处使用可能会导致问题,因此请谨慎使用。

$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Feb 22 19:47 file 1
-rw-rw-r--. 1 saml saml 0 Feb 22 19:47 file 2

$ du -sh * | sort -h | awk 'NR<=10 {print $2}' | tr "\n" " "
file file $
Run Code Online (Sandbox Code Playgroud)

我会使用该cut -f2-方法,但这只是我,其他人可能会为您提供更复杂的awk解决方案,但请使用对您最有意义的方法。

使用 awk + ​​cat

注意:当管道输出xargs不需要调用时catxargs默认情况下将自动回显它传递的输出。

$ du -sh * | sort -h | tail | cut -f2- | tr "\n" " " | xargs
file 1 file 10 file 2 file 3 file 4 file 5 file 6 file 7 file 8 file 9
Run Code Online (Sandbox Code Playgroud)

编辑#1

如果您使用制表符用 cut 分隔,则不需要明确这样做,它默认为。

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter
Run Code Online (Sandbox Code Playgroud)