33

I am trying to copy a project to my server with rsync. I have project specific install scripts in a subdirectory

project/specs/install/project1

What I am trying to do is exclude everything in the project/specs directory but the project specific install directory: project/specs/install/project1.

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

But like this the content of the specs directory gets excluded but the install/project1 directory does not get included.

I have tried everything but i just don't seem to get this to work

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
user1036651
  • 407
  • 1
  • 5
  • 12
  • 1
    Just found a similar question on linuxquestions.org which may help: http://www.linuxquestions.org/questions/linux-software-2/rsync-include-exclude-problems-636504/ – Chris Nov 25 '11 at 14:39
  • 1
    Thank you, that solved it! Rsync really has a strange logic sometimes. – user1036651 Nov 25 '11 at 14:59
  • 1
    Duplicates http://stackoverflow.com/questions/7960669/with-rsync-how-do-includes-and-excludes-combine/7961687#7961687 – Joao Figueiredo Nov 25 '11 at 17:58
  • 2
    Does the order of --include and --exclude matter? UPDATE: I just answered my own question: it does matter. I can't get it to work with --exclude before --include, but it does work with --include before --exclude. – Geremia Nov 12 '12 at 01:57

3 Answers3

40

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.

Ross Rogers
  • 23,523
  • 27
  • 108
  • 164
spider
  • 1,164
  • 9
  • 16
15

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.

lodc
  • 151
  • 1
  • 3
2

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.

Akif
  • 6,018
  • 3
  • 41
  • 44