Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a directory tree under ./src/

I have another matching directory tree under ./work/

I'm trying to copy all the files in src to work, while keeping the directory structure and excluding all files that end in .java.

Here's my attempt so far:

find src -type f ! -iname *.java -exec cp {} work \;

This almost works, but all the files are put into the top level under work, instead of into the correct place in the directory tree.

How can I do this? (using bash on Mac OS X 10.9)

share|improve this question
up vote 3 down vote accepted

tar cCf /source/path - --exclude "*.java" . | tar xCf /target/path -

share|improve this answer
That's some creative thinking! Worked like a charm, and I'd have never though to use tar. – Steve McLeod Apr 16 '14 at 16:00
rsync -a --exclude='*.java' src/ work/
share|improve this answer

You can use {} multiple times. So:

find src -type f ! -iname '*.java' -exec cp {} work/{} \;

will try and preserve path (and fail, because the directory probably doesn't exist. - however you could probably do:

-exec mkdir -p `dirname {}` \;

However, for what you're doing, you probably want to use tar:

find src -type f ! -iname '*.java' | xargs tar cvf - | ( cd work && tar xvf - )
share|improve this answer
Just tried running it. Seems to work, assuming you have both 'src' and 'work' in the cwd. (And the 'find' returns some files) ` – Sobrique Apr 16 '14 at 18:42
Typo on my part - mea culpa. – Chris S Apr 16 '14 at 18:46

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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