How does 'find -exec' pass file names with spaces?

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.


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.