Search code examples
rsync

rsync include specific files and exclude directory


I have a directory structure as below:

base
├── config.yml
├── build
│   └── output.yml
│   └── <multiple level sub-directories each having many files including *.c and *.h files>
├── <source directories - having many sub-directories with various files including *.c and *.h files>
│   ├── <xyz>
|   │   ├── <x1>
|   │   .
│   |   └── <xy>
│   .
│   .
│   └── <abc>
├── <more directories, each having multiple files including *.c and *.h files>

I need to sync this directory to remote, but I only need *.c and *.h files. Also complete 'build' directory needs to be excluded. I am running below command:

rsync -avm --include '*/' --include='*.c' --include='*.h' --exclude='*' base "$target_loc"

This is syncing all *.c and *.h files which is desired but it also syncs *.c and *.h files from build and its sub directories

I tried rsync -avm --include '*/' --include='*.c' --include='*.h' --exclude='build' --exclude='*' base "$target_loc". It still syncs files from build and it's sub directories.

How can I fix this?


Solution

  • You need to put --exclude='build' before --include '*/'. Both of these rules could apply to the "build" directory, and whichever is given first takes precedence, so to get the --exclude rule to override the --include rule, you need to list it first.

    From the rsync man page, in the FILTER RULES section (with my emphasis):

    As the list of files/directories to transfer is built, rsync checks each name to be transferred against the list of include/exclude patterns in turn, and the first matching pattern is acted on: if it is an exclude pattern, then that file is skipped; if it is an include pattern then that filename is not skipped; if no matching pattern is found, then the filename is not skipped.