Bash Binary Safe Handling
Binary-safe handling is moving bytes through bash without changing them. Text tools assume lines of text, so binary data needs byte-exact commands.
Print a leading dash exactly with printf %s
The value starts with a dash, which some commands read as an option. printf %s prints the value itself, dash and all.
v='-n hello'
printf '%s\n' "$v"Split NUL-delimited input with read -d ''
The input holds three items split by NUL bytes, and the third holds a space. Each read stops at a NUL byte, so the space stays inside its item.
printf 'a\0b\0c d\0' | while IFS= read -r -d '' item; do printf '[%s]\n' "$item"; doneCount file names that hold spaces
The input lists two file names split by NUL bytes, and each name holds a space. A line-based list would still work here, but a name with a newline would break it, while this NUL list holds.
printf 'my file\0other file\0' | {
n=0
while IFS= read -r -d '' f; do
n=$((n + 1))
printf '%s\n' "$f"
done
printf 'count=%s\n' "$n"
}Example
printf 'alpha file\0beta file\0' > names.nul
n=0
while IFS= read -r -d '' f; do
n=$((n + 1))
printf 'file: %s\n' "$f"
done < names.nul
printf 'count=%s\n' "$n"Key points
- printf %s: prints a value exactly, even when it starts with a dash.
- read -d '': reads up to a NUL byte, so NUL-delimited input splits safely.
- IFS=: an empty IFS stops read from trimming spaces in file names.
- Spaces and newlines: NUL-delimited names survive spaces, unlike line-based lists.
- Honest limit: a bash string cannot hold a NUL byte, so a NUL becomes a separator, never data inside one variable.
- Files, not variables: keep true binary bytes in files and pipes, and pass them with tools that handle NUL bytes.
In this example, the script first writes a NUL-delimited list of two file names. The loop reads each name up to its NUL byte, with an empty IFS so spaces stay intact. Each name prints with a file label, the counter grows, and the final line prints the count.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What can a bash string NOT hold?