如何将整个标准输入逐字转换为命令行参数?

如何将整个标准输入逐字转换为命令行参数?

尝试1

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

但这并不能保留零字节。该程序也可能运行多次。但是,它不会在零字节进入标准输入的情况下失败,而是多次运行程序。

尝试2

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

但这并不能保留尾随空白。

尝试3

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

似乎弄乱了终端,也无法保留尾随空格。


如何正确、可靠、可读、兼容地做到这一点?

答案1

命令行参数中不可能有 NUL 字节,所以问题是如果出现这种情况你希望发生什么标准输入中的 NUL 字节。

正如您所指出的,在这种情况下,您的候选解决方案#1 多次运行该命令。这并不理想。但没有理想的解决方案可以让您处理真正的二进制输入。在我看来,您唯一的其他合理选择是:

  • 删除 NUL 字节并继续
    • 插入tr -d '\0' |之前xargs
  • 将 NUL 字节转换为其他字节并继续
    • 插入tr '\0' something-else |之前xargs(如果something-else是单个字节)
  • 如果存在 NUL 字节,则中止并保释

    • 使用 bash 或 ksh93(除非输入末尾包含单个空字节,在这种情况下它将被静默删除):

      { 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
      }
      
    • 使用 zsh(而不是使用其他 shell,例如 bash、ksh 或 dash):

      input=$(<&0)
        if [[ $input != *$'\0'* ]]; then
          printf %s "$input" | xargs …;
        else
          echo 1>&2 "Null bytes detected, bailing out"
          exit 2
        fi
      
    • 或者使用临时文件。
  • 在第一个 NUL 字节之后截断输入

    • 插入tr '\0\n' '\n\0' | head -n 1 | tr '\0\n' '\n\0'之前xargs(假设你head是空安全的)

相关内容