Search code examples
bashshglobcp

cp -r * except dont copy any .pdf files - copy a directory subtree while excluding files with a given extension


Editor's note: In the original form of the question the aspect of copying an entire subtree was not readily obvious.

How do I copy all the files from one directory subtree to another but omit all files of one type?

Does bash handle regex?

Something like: cp -r !*.pdf /var/www/ .?

EDIT 1

I have a find expression: find /var/www/ -not -iname "*.pdf"

This lists all the files that I want to copy. How do I pipe this to a copy command?

EDIT 2

This works so long as the argument list is not too long:

sudo cp `find /var/www/ -not -iname "*.pdf"` .

EDIT 3

One issue though is that I am running into issues with losing the directory structure.


Solution

  • Bash can't help here, unfortunately.

    Many people use either tar or rsync for this type of task because each of them is capable of recursively copying files, and each provides an --exclude argument for excluding certain filename patterns. tar is more likely to be installed on a given machine, so I'll show you that.

    Assuming you are currently in the destination directory, the shell command:

    tar -cC /var/www . | tar -x
    

    will copy all files from /var/www into the current directory recursively.

    To filter out the PDF files, use:

    tar -cC /var/www --exclude '*.pdf' . | tar -x
    

    Multiple --exclude arguments can be given, so:

    tar -cC /var/www --exclude '*.pdf' --exclude '*.txt' . | tar -x
    

    would exclude .txt files as well.