Linux Basics: Pass Difficult Filenames from find to xargs
A filename can contain spaces, quotes, and even newlines. A pipeline that splits paths on whitespace can accidentally turn one file into several arguments. NUL separators preserve the path boundaries through every stage.
Prepare a scratch directory
Tested on Linux with GNU coreutils 9.7, GNU findutils 4.10.0, and GNU Bash 5.2.37. You need Bash, a text editor, and the utilities used below. The script creates its own temporary fixture directory and removes only that directory on exit.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1Run the example
Save this as demonstrate-find-xargs-null-paths.sh:
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fixture_dir="$(mktemp -d)"
trap 'rm -rf -- "$fixture_dir"' EXIT
cd -- "$fixture_dir"
mkdir inputs empty
touch -- 'inputs/alpha beta.txt' $'inputs/line\nbreak.txt' 'inputs/-leading.txt'
printf 'Escaped arguments received by Bash:\n'
find inputs -type f -print0 | sort -z | xargs -0 -r bash -c 'printf "%q\n" "$@"' show-paths
printf 'An empty match set runs no command:\n'
find empty -type f -print0 | xargs -0 -r printf 'UNEXPECTED\n'
printf 'Done\n'Run it:
bash demonstrate-find-xargs-null-paths.shObserved output:
Escaped arguments received by Bash:
inputs/-leading.txt
inputs/alpha\ beta.txt
$'inputs/line\nbreak.txt'
An empty match set runs no command:
DoneRead the result
find -print0 terminates each path with a NUL byte. GNU sort -z retains those record boundaries while making the display order repeatable. xargs -0 reads the same format. The fixed Bash program receives paths as separate arguments in "$@"; it does not splice their text into shell source. show-paths occupies Bash’s $0, so the first path remains in $1. Bash printf %q displays shell-escaped representations, including the embedded newline.
Apply it carefully
GNU xargs -r skips the command when there are no records. NUL delimiters solve argument boundaries, not races: another process can rename or replace files between discovery and use. This example only previews arguments in a controlled directory. Paths begin with inputs/, so the leading hyphen in one basename is not a command option. For a real consumer, also follow its end-of-options convention where supported. Do not replace the fixed script with generated shell code or eval.
The GNU reference documents these options and their behavior.
Clean up
Remove the saved script, return to the starting directory, and remove the empty practice directory:
rm -- demonstrate-find-xargs-null-paths.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirIf the directory is not empty, inspect what remains rather than deleting unknown files.
Acknowledgements
This post was created with assistance from AI.