Como faço para transformar todo o stdin em um argumento de linha de comando verbatim?

2

Tentativa 1

xargs -I '{}' -0 -n 1 myprogram --arg '{}' --other-options

Mas isso não preserva zero bytes. Além disso, o programa pode ser executado várias vezes. Mas, em vez de falhar no caso de zero byte rastejar em stdin, ele executa o programa várias vezes.

Tentativa 2

myprogram --arg "'cat'" --other-options

Mas isso não preserva o espaço em branco.

Tentativa 3

bash -c 'read -r -d "" INPUT ; myprogram --arg "$INPUT" --other-options'

Parece que a bagunça do terminal também não preserva o espaço em branco.

Como faço isso de maneira correta, confiável, legível, compatível?

    
por Vi. 14.01.2016 / 23:59

1 resposta

6

É impossível ter bytes NUL em argumentos de linha de comando , então a questão é o que você quer que aconteça caso haja bytes NUL na entrada padrão.

Como você observou, sua solução candidata nº 1 executa o comando várias vezes neste caso. Isso não é ideal. Mas não há solução ideal que permita lidar com entradas binárias verdadeiras. Do meu ponto de vista, suas únicas outras opções razoáveis aqui são:

  • elimine os bytes NUL e continue
    • insira tr -d 'xargs' | antes de tr 'xargs' something-else |
  • traduza os bytes NUL para outra coisa e prossiga
    • insira something-else antes de tr 'xargs\n' '\nhead' | head -n 1 | tr '%code%\n' '\n%code%' (se %code% for um único byte)
  • aborte e solte no caso de existirem bytes NUL

    • com bash ou ksh93 (exceto se a entrada contiver um único byte nulo no final, caso em que ele é silenciosamente excluído):

      { read -r -d '' input;
        if [ "$(wc -c)" = 0 ]; then
          printf %s "$input" | xargs …;
        else
          echo 1>&2 "Null bytes detected, bailing out"
          exit 2
        fi
      }
      
    • com zsh (e não com outros shells como bash, ksh ou dash):

      input=$(<&0)
        if [[ $input != *$'
      { read -r -d '' input;
        if [ "$(wc -c)" = 0 ]; then
          printf %s "$input" | xargs …;
        else
          echo 1>&2 "Null bytes detected, bailing out"
          exit 2
        fi
      }
      
      '* ]]; then printf %s "$input" | xargs …; else echo 1>&2 "Null bytes detected, bailing out" exit 2 fi
    • Ou use um arquivo temporário.
  • trunca a entrada após o primeiro byte NUL

    • insira %code% antes de %code% (supondo que seu %code% seja nulo)
por 15.01.2016 / 00:42