Usually you'd want to use find -exec
to run a command for all file names, or find -print0
to pipe the names to some command that can read entries separated by nul bytes (like xargs -0
).
If you really want to have quoted strings, Bash has a couple of options to do that:
$ find -exec bash -c 'printf "%s\n" "${@@Q}"' sh {} +
'./single'\''quote'
'./space 1'
$'./new\nline'
'./double"quote'
$ find -exec bash -c 'printf "%q\n" "$@"' sh {} +
./single\'quote
./space\ 1
$'./new\nline'
./double\"quote
This does require an extra invocation of the shell, but handles multiple file names with one exec.
Regarding saving the permission bits (not ACL's though), you could do something like this (in GNU find):
find -printf "%#m:%p\0" > files-and-modes
That would output entries with the permissions, a colon, the filename, and a nul byte, like: 0644:name with spaces\0
. It will not escape anything, but instead will print the file names as-is (unless the output goes to a terminal, in which case at least newlines will be mangled.)
You can read the result with a Perl script:
perl -0 -ne '($m, $f) = split/:/, $_, 2; chmod oct($m), $f; ' < files-and-modes
Or barely in Bash, see comments:
while IFS=: read -r -d '' mode file ; do
# do something useful
printf "<%s> <%s>\n" "$mode" "$file"
chmod "$mode" "$file"
done < files-and-modes
As far as I tested, that works with newlines, quotes, spaces, and colons. Note that we need to use something other than whitespace as the separator, as setting IFS=" "
would remove trailing spaces if any names contain them.
find -exec
instead, which obviates the need to escape any shell metacharacters. – tripleee Apr 19 '17 at 10:33nul
-terminated paths, then just use-print0
. – Kusalananda Apr 19 '17 at 10:34getfacl
to backup ACLs, which executes terribly slow on large filesystems. Withfind
I could easily print filenames and permissions in octal format into a file and easily restore them withchmod $1 $2
. But this won't work if $2 has special characters. – Julen Larrucea Apr 19 '17 at 12:04find
. – ilkkachu Apr 19 '17 at 12:45find
can just be slow.I'll just comment that another use case for outputting escaped filenames is the situation where thefind
command takes a long time to run, and you don't know up front what you want to do with those files. I was just in that situation; I had to look at the content of the files, eliminate some irrelevant ones, and then interpret the JSON in the remaining files to find a path to a different file. There were a number of false steps in the latter, and having a plain text file containing the output avoided the need to runfind
each time. – Mike Maxwell Jun 01 '23 at 20:02