find: Copying A Subset of Files
10.2 Copying A Subset of Files
==============================
Suppose you want to copy some files from '/source-dir' to '/dest-dir',
but there are a small number of files in '/source-dir' you don't want to
copy.
One option of course is 'cp /source-dir /dest-dir' followed by
deletion of the unwanted material under '/dest-dir'. But often that can
be inconvenient, because for example we would have copied a large amount
of extraneous material, or because '/dest-dir' is too small. Naturally
there are many other possible reasons why this strategy may be
unsuitable.
So we need to have some way of identifying which files we want to
copy, and we need to have a way of copying that file list. The second
part of this condition is met by 'cpio -p'. Of course, we can identify
the files we wish to copy by using 'find'. Here is a command that
solves our problem:
cd /source-dir
find . -name '.snapshot' -prune -o \( \! -name '*~' -print0 \) |
cpio -pmd0 /dest-dir
The first part of the 'find' command here identifies files or
directories named '.snapshot' and tells 'find' not to recurse into them
(since they do not need to be copied). The combination '-name
'.snapshot' -prune' yields false for anything that didn't get pruned,
but it is exactly those files we want to copy. Therefore we need to use
an OR ('-o') condition to introduce the rest of our expression. The
remainder of the expression simply arranges for the name of any file not
ending in '~' to be printed.
Using '-print0' ensures that white space characters in file names do
not pose a problem. The 'cpio' command does the actual work of copying
files. The program as a whole fails if the 'cpio' program returns
nonzero. If the 'find' command returns non-zero on the other hand, the
Unix shell will not diagnose a problem (since 'find' is not the last
command in the pipeline).