How can find
search results containing spaces to be printed with enclosing ''
(a quote pair). Only if this result contains spaces, if there are not spaces in the path string, to remain as is.

- 8,122
3 Answers
Here is a way to do it using just find
if your version supports -printf.
find . -name "* *" -printf "\"%p\"\n" -o -print

- 136
- 4
-
Note: From Stéphane Chazelas, you may want to set
LC_ALL=C
before this command so that the '*' will match bytes that are not valid characters. That is probably not necessary 99.9% of the time, so I think it should be here as a note instead of in the answer. – bdowling Oct 28 '20 at 07:13 -
Edited. Thanks, Stéphane. That is probably what most people would want. – bdowling Oct 29 '20 at 08:23
Assuming you want to generate CSV output, with GNU tools:
find . -print0 |
LC_ALL=C sed -z '/[",[:space:]]/{s/"/""/g; s/.*/"&"/}' |
tr '\0' '\n'
That is, as long as the file name contains at least one "
, ,
or ASCII whitespace character (including, but not limited to SPC, TAB, CR and newline all special in CSV), translate "
to ""
(which is how most CSV formats escape the "
s), and enclose the string in double quotes.
That part is done using NUL as the record delimiter since it's the only byte that can't occur in a file path. And then, we translate NULs to newline with tr
.
On non-GNU systems, you can always resort to perl
:
find . -print0 | perl -l -0 -pe 'if (/[",\s]/) {s/"/""/g; $_ = "\"$_\""}'
After
touch 'a b' $'a\nb' a,b a_b $'a\200b' 'a"b'
They give:
.
"./a""b"
./a_b
"./a,b"
./a�b
"./a
b"
"./a b"
(where �
is my terminal's rendition of that \200
byte that doesn't form a valid character in my UTF-8 locale).
To exclude .
and the ./
prefix, replace -print0
with -mindepth 1 -printf '%P\0'
(though -printf
is GNU-specific). Which gives:
"a""b"
a_b
"a,b"
a�b
"a
b"
"a b"
-print0
and -mindepth
are also GNU extensions, but they have since been copied to a few other implementations. If your implementation is one of the few where that still don't have them, you can replace:
find . -print0
withfind . -exec printf '%s\0' {} +
find . -mindepth 1 -printf '%P\0'
withfind . ! -name . -exec sh -c 'for i do printf "%s\0" "${i#./}"; done' sh {} +

- 544,893
You can do it by piping the output to awk
:
find . | awk '/ /{ printf"\"%s\"\n", $0; next } { print }'

- 136
- 4
-print0
if yourfind
implementation supports it – steeldriver Oct 28 '20 at 01:49-path '* *' -printf '"%p"\n' -o -print
I suppose – steeldriver Oct 28 '20 at 04:31-print0
you can reliably do something to a file (with any valid name) thanks to-exec
. – Kamil Maciorowski Oct 28 '20 at 06:18