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.
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.
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?
find demo | cpio -p demo_bkp
finds files matching whatever criteria you want and uses cpio to copy them (so-called "pass-through" mode).
find -depth
changes the order the files are printed in to match the order cpio wants.
find -name .git -prune
tells find not to recurse down .git
directories.
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.
cpio -d
creates directories as needed.
cpio -v --quiet
prints each file name while omitting the "X blocks copied" message cpio normally prints at the end.
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).
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.