I have two same-size flash cards, and I want to copy contents of one to the other based on the following rules:

  1. I want all directories and subdirectories in place
  2. I want to exclude files of type .FOO, .BAR, and .ZIM (all other files are copied)
  3. Bonus: It'd be cool if it outputs the filenames as they are copied considering it will be copying ~8 GB of information

Could this be done with "find" somehow?

link|improve this question

78% accept rate
You can edit your question and change the title. – Dennis Williamson Feb 5 '10 at 16:14
Ahh, there's the little "edit" link :) – macek Feb 5 '10 at 16:17
rsync is awesome :) – Rory Feb 5 '10 at 16:34
feedback

2 Answers

up vote 7 down vote accepted

This would be significantly easier using rsync with its --exclude switch.

rsync -av --exclude='*.FOO' --exclude='*.BAR' --exclude='*.ZIM' /source /dest

The -v switch will provide verbose output on which files are being synchronised.

link|improve this answer
This is wonderful, thank you (again). I'll update this post and include an rsync tag :) – macek Feb 5 '10 at 16:32
You're more than welcome :) – John T Feb 5 '10 at 16:33
Little follow-up here: the copy finished and /src/* is now in /dest/src/* How to use rsync to get /src/* in /dest/*? – macek Feb 5 '10 at 17:32
Try /source/ /dest – John T Feb 5 '10 at 17:44
feedback

One slightly silly way is to use tar (GNU tar).

cd /media/dest
tar --exclude="*.(FOO|BAR|ZIM)$" cf -  /media/source | tar xf - 

Others could include doing a single column recursive list (ls -R1), excluding patterns via grep (grep -ev ".(FOO|BAR|ZIM)$") , and passing those to xargs cp.

link|improve this answer
Thanks for this. The rsync solution works good for me but I can see this being useful for other things :) – macek Feb 5 '10 at 18:20
The dot in the grep regex should be escaped. Parentheses are from extended regexes, so use egrep or grep -E. The output of ls -R1 is not right for xargs. With xargs cp (e.g. xargs -J+ cp + /path/to/dest?) the subdirs structure would be flattened out. --exclude uses ‘globbing’, not regexes. The $ should not be there, and the parentheses can not be used like that with globs. Use multiple --exclude options or put them in a file and use --exclude-from. (cd /path/to/source && tar --exclude='*.FOO' --exclude='*.BAR' --exclude='*.ZIM' -cf - . | (cd /path/to/dest && tar xf -) – Chris Johnsen Feb 6 '10 at 10:11
+1 Chris. Thanks Chris for the constructive and helpful comment, I didn't test the either method, silly me. – mctylr Feb 7 '10 at 19:11
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.