cp command should ignore some files

To ignore a git directory specifically, I'd try git export first.

But in general, to copy a directory tree excluding certain files or folders, 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.


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.


Continuing on the rsync idea, if you have so many file patterns to ignore, you can use the --exclude-from=FILE option.

The --exclude-from=FILE option takes a file [FILE] that contains exclude patterns (one pattern per line) and excludes all the files matching the patterns.

So, say you want to copy a directory demo to demo_bkp, but you want to ignore files with the patterns - .env, .git, coverage, node_modules. You can create a file called .copyignore and add the patterns line by line to .copyignore:

.env
.git
coverage
node_modules

Then run:

rsync -rv --exclude-from=./.copyignore demo demo_bkp

That's it. demo would be copied into demo_bkp with all the files matching the patterns specified in .copyignore ignored.


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