views:

42

answers:

3

Sometimes I need to perform following command

cp -rv demo demo_bkp

However I want to ignore all the files in directory .git . How do I achieve that? It takes a long time to copy .git files and I do not need those files.

+2  A: 

OK. Brace yourself. This isn't pretty.

find demo -depth -name .git -prune -o -print0 | cpio -0pdv --quiet demo_bkp

What's going on here?

  1. find demo | cpio -p demo_bkp finds files matching whatever criteria you want and uses cpio to copy them (so-called "pass-through" mode).

  2. find -depth changes the order the files are printed in to match the order cpio wants.

  3. find -name .git -prune tells find not to recurse down .git directories.

  4. find -print0 | cpio -0 has find use NUL characters (\0) to separate file names. This is for maximum robustness in case there are any weirdly-named files with spaces, newlines, or other unusual characters.

  5. cpio -d creates directories as needed.

  6. cpio -v --quiet prints each file name while omitting the "X blocks copied" message cpio normally prints at the end.

John Kugelman
I might not use this solution for the given case but thanks for illustrating your answer. I am sure I'll use it some other time.
Nadal
+1  A: 

I think this will do the trick:

cd demo
find . -not -path \*/.\* -type d -exec mkdir -p -- ../demo_bkp/{} \;
find . -not -path \*/.\* -type f -exec cp -- {} ../demo_bkp/{} \;

First finds and creates each directory. Then finds and copies each file.

Note it will not work with special files (symbolic links, etc).

LatinSuD
+4  A: 

In this instance I'd recommend using rsync instead of cp. The syntax is mostly the same, but rsync has way more options, including one to exclude selected files:

rsync -rv --exclude=.git demo demo_bkp

See e.g. the man page for more info.

David Zaslavsky
+1 for recommending rsync instead of cp for this problem
whaley