rsync exclude a directory but include a subdirectory rsync exclude a directory but include a subdirectory shell shell

rsync exclude a directory but include a subdirectory


Sometime it's just a detail.

Just change your include pattern adding a trailing / at the end of include pattern and it'll work:

rsync -avz --delete --include=specs/install/project1/ \    --exclude=specs/* /srv/http/projects/project/ \    user@server.com:~/projects/project

Or, in alternative, prepare a filter file like this:

$ cat << EOF >pattern.txt> + specs/install/project1/> - specs/*> EOF

Then use the --filter option:

rsync -avz --delete --filter=". pattern.txt" \    /srv/http/projects/project/ \    user@server.com:~/projects/project

For further info go to the FILTER RULES section in the rsync(1) manual page.


The other solution is not working here.


Reliable way

You have no choice but to manually descend for each level of your sub-directory. There is no risk to include unwanted files, as rsync doesn't include the files of included directories.

1) Create an include filter file, for instance "include_filter.txt":

+ /specs/+ /specs/install/+ /specs/install/project1/***- /specs/**

2) Run it:

rsync -avz --delete --include-from=include_filter.txt \    /srv/http/projects/project/ \    user@server.com:~/projects/project
  • Don't forget the starting slash "/", otherwise you may match sub-directories named "**/specs/install/project1/".
  • By choosing an include type filter (--include-from=FILE), the starting plus "+" signs are actually optional, as this is the default action with no sign. (You can have the opposite "-" by default with --exclude-from=FILE.)
  • The double stars "**" means "any path"
  • The triple stars "***" means "any path, including this very directory"

Easy way

You can start your filters "*/", allowing rsync to descend all your sub-levels. This is convenient but:

  • All directories will be included, albeit empty. This can be fixed with the rysnc option -m, but then all empty dirs will be skipped.

1) Create an include filter file, for instance "include_filter.txt":

+ /**/+ /specs/install/project1/***- /specs/**

2) Run it:

rsync -avzm --delete --include-from=include_filter.txt \    /srv/http/projects/project/ \    user@server.com:~/projects/project

Note the added option -m.


Order of --include and --exclude affects what is being included or excluded.
When there are particular subdirectories to be included need to place them first.
Similar post available here.