Quando você deve usar subshells vs 'xargs'?

6

Muitos comandos simples usando xargs podem ser reescritos como comandos usando subshells. Por exemplo, aqui está algo que eu estava usando hoje cedo, para concatenar os dez maiores binários em /usr/bin , escritos usando um subshell vs xargs:

subshell:

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

xargs :

$ du -sh /usr/bin/* | sort -h | tail | cut -d "      " -f 2 | tr "\n" " " | xargs cat

Então, quando você deve usar um subshell e quando você deve usar xargs ?

NOTA:

O delimitador para corte é uma guia difícil, que aparentemente não é exibida corretamente no SE.

    
por haneefmubarak 22.02.2014 / 23:20

1 resposta

6

Esta é uma pergunta levemente opinativa, mas vou apenas dizer isso, é altamente dependente de duas coisas:

  1. Qual é o comando que você vai executar?
  2. Quantas instâncias você vai executar?

Se você for capaz de executar dezenas a 100 do mesmo processo, então xargs faz mais sentido. Além disso, se os processos começarem a ser caros, xargs provavelmente será o melhor caminho a percorrer.

Se, no entanto, existir apenas um punhado de instâncias do comando, então executá-las em um subshell é aceitável.

Se o comprimento dos argumentos produzidos pelo subshell for extremamente longo, você deverá usar xargs . Mas esse limite é bem extremo, tipicamente 2MB-4MB de caracteres, então é improvável que você o exceda. Você pode checar assim:

$ 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

A propósito, nenhum desses comandos parece funcionar. O cut -d " " -f2 não é válido, cut só pode ter um único caractere como o delimitador. Tente isso:

$ 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" " "

Usar awk aqui provavelmente causará problemas se você tiver nomes de arquivos ou diretórios com espaços, portanto, use-o com cuidado.

$ 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 $

Eu usaria o método cut -f2- , mas sou eu, os outros podem oferecer uma solução awk mais sofisticada, mas use o que for mais adequado para você.

Usando o awk + cat

OBSERVAÇÃO: Quando a saída da tubulação for xargs , não será necessário chamar cat , xargs fará o eco automaticamente da saída pela qual passou, por padrão.

$ 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

EDIT # 1

Se você estiver usando guias para delimitar com recorte, não será necessário explicá-lo.

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter
    
por 23.02.2014 / 01:58