0

I'm looking for a CLI tool that takes an arbitrary number of arguments $a, $b, $c, $d, etc., and writes $a"\0"$b"\0"$c"\0"$d to stdout. Is there a standard tool that can do this that I can just use in the beginning of a pipe on the CLI? My implementation of echo doesn't seem to allow for custom delimiters.

UTF-8
  • 3,237

2 Answers2

4

printf can take care of this, nearly:

printf "%s\0" "$a" "$b" "$c" ...

printf repeats its format string as much as necessary, in this case once per argument, so you end up with each argument followed by a null byte.

To get rid of the last null byte, use GNU head:

printf "%s\0" "$a" "$b" "$c" ... | head -c-1

Zsh’s builtin print can also do this, with no post-processing:

print -rNn "$a" "$b" "$c" ...

(-r disables escape processing, -N prints the arguments separated and terminated by null bytes, -n disables the terminal newline. Thanks steeldriver for the tip!)

Stephen Kitt
  • 434,908
  • Thanks! SE doesn't allow me to accept until 10 minutes have passed. Will accept shortly. – UTF-8 Jul 05 '19 at 13:25
3

The printf command will repeat the format as often as necessary, so we can just do

print "%s\0"

We can see this in action:

$ printf "%s\0" hello there | hdump -8                   
00000000  68 65 6C 6C 6F 00 74 68   hello.th
00000008  65 72 65 00               ere.

$ printf "%s\0" hello there everyone out there | hdump -8
00000000  68 65 6C 6C 6F 00 74 68   hello.th
00000008  65 72 65 00 65 76 65 72   ere.ever
00000010  79 6F 6E 65 00 6F 75 74   yone.out
00000018  00 74 68 65 72 65 00      .there.

Note that is also puts a terminal NUL at the end of the string. If you don't want that, we can remove it, eg with sed 's/.$//'

$ printf "%s\0" hello there everyone out there | sed 's/.$//' | hdump -8
00000000  68 65 6C 6C 6F 00 74 68   hello.th
00000008  65 72 65 00 65 76 65 72   ere.ever
00000010  79 6F 6E 65 00 6F 75 74   yone.out
00000018  00 74 68 65 72 65         .there