A filename can contain spaces, tabs and newline characters. Treating find output as one filename per line therefore corrupts valid paths. Use a NUL delimiter for machine processing and preserve each path as one quoted shell value.

This example counts three files and sums their content lengths. One filename contains a space, another contains a literal newline, and another starts with a dash. It writes a temporary NUL-delimited manifest so a failed find command is checked separately from the loop that consumes its output.

Prerequisites

Use Linux with Bash, GNU findutils, mktemp and wc. Save the program as names.sh in a writable scratch directory. The newline in the second filename below is intentional.

#!/usr/bin/env bash
set -euo pipefail
root=$(mktemp -d ./names-demo.XXXXXX)
trap 'rm -rf -- "$root"' EXIT
mkdir "$root/input"
printf 'x' > "$root/input/a b.txt"
printf 'yy' > "$root/input/line
break.txt"
printf 'zzz' > "$root/input/-dash.txt"
find "$root/input" -type f -print0 > "$root/paths.bin"
count=0
bytes=0
while IFS= read -r -d '' path; do
    size=$(wc -c < "$path")
    bytes=$((bytes + size))
    count=$((count + 1))
done < "$root/paths.bin"
test "$count" -eq 3
test "$bytes" -eq 6
printf 'files=%s bytes=%s\n' "$count" "$bytes"
find "$root/input" -type f -name '*.missing' -print0 > "$root/empty.bin"
test ! -s "$root/empty.bin"
printf 'empty selection checked\n'

Run and expected output

bash names.sh
files=3 bytes=6
empty selection checked

Follow each boundary

find emits the complete pathname followed by a NUL byte. Bash read uses that delimiter, disables backslash processing with -r, and avoids whitespace trimming through the empty IFS assignment. Quoting path when opening the file preserves the entire name.

The loop receives input through redirection instead of a pipeline, so its counter changes remain in the current shell. The byte counter reads wc output; it does not place the NUL-delimited manifest inside command substitution. Shell variables cannot represent embedded NUL bytes, so the manifest belongs in a file or pipe.

Input redirection gives wc the file contents through standard input. The unusual filename is never interpreted as a wc option. The manifest and empty-selection output live outside the searched input directory, so neither becomes an accidental input file.

Edge cases and troubleshooting

Run this with bash, not sh: the read delimiter option is part of the chosen Bash interface. A script pasted through an editor that changes the literal filename newline should still count three files, but would no longer test that specific edge case.

This counts bytes, not characters; multibyte UTF-8 content would produce a different character count. Symbolic links are not included by this particular find invocation. File order is irrelevant because the result is an aggregate.

A manifest preserves path boundaries, not a filesystem snapshot. A file can disappear or change after discovery; an unreadable file causes this script to stop. For a production report, decide whether such changes should abort processing or produce explicit per-file errors. The example tests a stable directory and an empty selection, then removes its temporary files.

Primary references

The GNU project documents unusual filename handling and findutils. More examples are available in Linux tutorials.