If I have a directory containing some files whose names have spaces, e.g.

$ ls -1 dir1
file 1
file 2
file 3

I can successfully copy all of them to another directory like this:

$ find dir1 -mindepth 1 -exec cp -t dir2 {} +

However, the output of find dir1 -mindepth 1 contains un-escaped spaces:

$ find dir1 mindepth 1
dir1/file 1
dir1/file 3
dir1/file 3

If I use print0 instead of print, the output still contains un-escaped spaces:

$ find dir1 mindepth 1 -print0
dir1/file 1dir1/file 2dir1/file 3

To copy these files manually using cp, I would need to escape the spaces; but it seems that this is unnecessary when cp's aguments come from find, irrespective of whether I use + or \; at the end of the command.

What's the reason for this?

3 Answers 3


The find command executes the command directly. The command, including the filename argument, will not be processed by the shell or anything else that might modify the filename. It's very safe.

You are correct that there's no need to escape filenames which are represented by {} on the find command line.

find passes the raw filename from disk directly into the internal argument list of the -exec command, in your case, the cp command.

  • 2
    In a nutshell, find..exec can handle weird filenames on its own..
    – heemayl
    Commented Nov 15, 2015 at 4:05
  • 4
    The first rule of linux club is you do not parse ls Commented Nov 15, 2015 at 4:41
  • 1
    Perhaps it's in reference to "passes the raw filename from disk directly into the internal argument list"
    – MrR
    Commented Sep 27, 2021 at 18:27
  • 1
    What do you do if you need a pipe in your exec command? The accepted answer on this site is to find . -exec sh -c "echo {} | wc -c" \; (as an example). But it seems to me like using exec this way doesn't follow the rules of this answer. Commented Apr 23, 2022 at 8:41
  • 1
    Ha! Thanks for taking the time to reply. I think I was extremely tired when I wrote that. Now that I'm alert... TL;DR: Does your answer apply when you want to use a pipe in an -exec string? In detail: By "accepted answer," I meant the highest voted answer for how to pipe commands in an -exec: stackoverflow.com/a/307154/61624 By "the rules of this answer," I meant, if I'd like to pipe commands in an -exec, it doesn't seem like I can use your answer: compared to -execing a single command, piping commands in -exec seems like an entirely different beast. Commented Apr 27, 2022 at 19:18

The question is two-part:

  • how does find manage to call programs using -exec without running into problems with spaces embedded in filenames, and
  • what good is the -print0 option?

For the first, find is making a system call, actually one of a group of related calls referred to as "exec". It passes the filename as an argument directly to this call, which then is passed directly (after creating a new process) without losing information about the filename.

The POSIX find feature + is explained as follows, in the rationale:

A feature of SVR4's find utility was the -exec primary's + terminator. This allowed filenames containing special characters (especially newline characters) to be grouped together without the problems that occur if such filenames are piped to xargs. Other implementations have added other ways to get around this problem, notably a -print0 primary that wrote filenames with a null byte terminator. This was considered here, but not adopted. Using a null terminator meant that any utility that was going to process find's -print0 output had to add a new option to parse the null terminators it would now be reading.

That "notably a -print0 primary" refers to GNU find and xargs which solve the problem in a different way. It is also supported by FreeBSD find and xargs. If you added a -0 option (see the manual page) to the xargs call, then that program accepts lines terminated by "null byte" characters. In turn, xargs calls exec-functions to do its work. The main distinction between the -print0 and -0 feature versus the + feature is that the former passes the filenames over a pipe, while the latter does not. Developers find uses for almost any feature; the pipes are no exception.

Back to OP's example, which uses a -t option to cp: that is not found in POSIX cp. Rather, it is an extension (aka "nonstandard feature") provided by GNU cp. The -0 extension of xargs would not improve this example, but there are other cases where it can be used effectively—keeping in mind that there is the portable alternative +, which GNU find accepts.


(This should be a comment but it's too large.)

For those who like to try things out:

Create a script listing positional parameters passed in, call it list_positional_parameters.sh.


# http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html
# Try globbing patterns, e.g. "X[[:digit:]][[:digit:]]" to see what happens

if [ $# -lt 1 ]; then
   echo "Usage: $0 and then at least one parameter"
   exit 1


while (($#)); do
   echo "$counter = '$1'"
   # pop positional argument 1 off the stack of positional arguments
   (( counter++ ))

Run find with it on some directory $dir:

find "$dir" -exec ./list_positional_parameters.sh '{}' ';' | less

As expected, there is only a single parameter in all calls, the filename, whether there are spaces in its name or not.

  • 2
    You may also use printf like printf '"%s"\n' "$@" to print out all positional argument quoted, for visual inspection.
    – Kusalananda
    Commented Jul 26, 2018 at 9:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .