In many versions of find, the operator {}
, used with the -exec operator, only works when it's separated from other
arguments by whitespace. So, for example, the following command will
not do what you thought it would:
% find . -type d -exec mkdir /usr/project/{} \;
You might have thought this command would make a duplicate set of (empty) directories, from the current directory and down, starting at the directory /usr/project. For instance, when the find command finds the directory ./adir, you would have it execute mkdir /usr/project/./adir (mkdir will ignore the dot; the result is /usr/project/adir).
That doesn't work because those versions of find don't recognize the {}
in the pathname. The GNU version does expand {}
in the middle of a string. On versions that
don't, though, the trick is to pass the directory names to sed
, which substitutes in the leading
pathname:
%find . -type d -print | sed 's@^@/usr/project/@' | xargs mkdir
%find . -type d -print | sed 's@^@mkdir @' | (cd /usr/project; sh)
Let's start with the first example. Given a list of directory names, sed substitutes the desired path to that
directory at the beginning of the line before passing the completed filenames to
xargs and mkdir.
An @
is used as a sed delimiter because slashes (/
) are needed in the actual text of the substitution. If you
don't have xargs, try the second example.
It uses sed to insert the mkdir command, then it changes to the target
directory in a subshell where the mkdir
commands will actually be executed.
— JP