3

Attempt 1

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

But that does not preserve zero bytes. Also the program may run multiple times. But instead of failing in case of zero byte creeping into stdin, it runs program multiple times.

Attempt 2

myprogram --arg "`cat`" --other-options

But that does not preserve trailing whitespace.

Attempt 3

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

Seems to mess with terminal, also fails to preserve trailing whitespace.


How do I do it properly, reliably, readably, compatibly?

Vi.
  • 5,688

1 Answers1

7

It is impossible to have NUL bytes in command line arguments, so the question is what do you want to happen in case there are NUL bytes in the standard input.

As you've noted, your candidate solution #1 runs the command multiple times in this case. That's not ideal. But there is no ideal solution that lets you handle true binary input. As I see it, your only other reasonable options here are to:

  • delete the NUL bytes and proceed
    • insert tr -d '\0' | before xargs
  • translate the NUL bytes to something else and proceed
    • insert tr '\0' something-else | before xargs (if something-else is a single byte)
  • abort and bail in case there are NUL bytes

    • with bash or ksh93 (except if the input contains a single null byte at the end, in which case it is silently deleted):

      { 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
      }
      
    • with zsh (and not with other shells such as bash, ksh or dash):

      input=$(<&0)
        if [[ $input != *$'\0'* ]]; then
          printf %s "$input" | xargs …;
        else
          echo 1>&2 "Null bytes detected, bailing out"
          exit 2
        fi
      
    • Or use a temporary file.
  • truncate the input after the first NUL byte

    • insert tr '\0\n' '\n\0' | head -n 1 | tr '\0\n' '\n\0' before xargs (assuming your head is null-safe)
Celada
  • 44,132