xargs - acrescenta cada argumento com um parâmetro

12

Eu sei disso, dado l="a b c" ,

echo $l | xargs ls

rendimentos

ls a b c

Quais resultados de construção

mycommand -f a -f b -f c
    
por not-a-user 16.05.2017 / 15:47

2 respostas

11

Uma maneira de fazer isso:

echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand

Isso pressupõe que a , b e c não contêm espaços em branco, novas linhas, citações ou barras invertidas. :)

Com o% GNUfindutil você pode lidar com o caso geral, mas é um pouco mais complicado:

echo -n "a|b|c" | tr \| \0 | xargs -0 printf -- '-f
... | xargs -x -0 mycommand
%s
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
' | xargs -0 mycommand

Você pode substituir o separador | por outro caractere que não aparece em a , b ou c .

Editar: como @MichaelMol observa, com uma lista muito longa de argumentos há um risco de transbordar o comprimento máximo de argumentos que podem ser passados para mycommand . Quando isso acontecer, o último xargs dividirá a lista e executará outra cópia de mycommand , e há o risco de deixar um -f não finalizado. Se você se preocupar com essa situação, poderá substituir o último xargs -0 acima por algo como isto:

echo -n "a|b|c" | tr \| \0 | xargs -0 printf -- '-f
... | xargs -x -0 mycommand
%s%pre%' | xargs -0 mycommand

Isso não resolverá o problema, mas interromperá a execução de mycommand quando a lista de argumentos ficar muito longa.

    
por 16.05.2017 / 15:59
5

Uma maneira melhor de abordar isso (IMO) seria:

  • em zsh :

    l=(a b c)
    mycommand -f$^l
    

    ou usando array zipping para que o argumento não seja anexado à opção:

    l=(a b c) o=(-f)
    mycommand "${o:^^l}"
    

    Dessa forma, ainda funciona se a matriz l contiver elementos vazios ou elementos que contenham espaços ou qualquer outro caractere problemático para xargs . Exemplo:

    $ l=(a '' '"' 'x y' c) o=(-f)
    $ printf '<%s>\n' "${o:^^l}"
    <-f>
    <a>
    <-f>
    <>
    <-f>
    <">
    <-f>
    <x y>
    <-f>
    <c>
    
  • em rc :

    l=(a b c)
    mycommand -f$l
    
  • em fish :

    set l a b c
    mycommand -f$l
    

(AFAIK, rc e fish não têm zipagem de matriz)

Com shells estilo Bourne como bash , você sempre pode fazer (ainda permitindo qualquer caractere nos elementos da matriz $@ ):

set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
    
por 16.05.2017 / 16:53