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).