0

I am trying to use rsync to backup a website on my raspberry pi, but when I specify include and exclude it is not recursing into subdirectories. I use the following command:

rsync -rva html/ /media/pi/DEC6-5E68/html/ --include '.htaccess' --include '*.html' --include '*.php' --exclude '*'

But I only am backing up the upper level and not recursing, despite the 'r' option. I think I have a basic misunderstanding of linux wildcards. It does recurse if I omit any include or exclude arguments.

3
  • My answer has not been accepted, so maybe it's not enough. Can I get some feedback? How can I help you more? Jul 11 '19 at 8:36
  • Sorry, I haven't had a chance to test it yet. But I will accept your answer by virtue of it being quite definitive.
    – RufusVS
    Jul 11 '19 at 17:08
  • I didn't mean to rush you; just thought maybe the problem is not entirely solved. To be clear: it's not about reputation points I get for accepted answer, it's about solving the problem. If it turns out after testing that the solution is not enough, please leave me a comment. And don't hesitate to unaccept if appropriate, I believe you can do this anytime. Jul 12 '19 at 8:01
1

Whenever a subdirectory is encountered, it gets excluded by the --exclude '*' statement and rsync doesn't descend.

This behavior is mentioned in the manual, with a solution. From man 1 rsync:

Note that, when using the --recursive (-r) option (which is implied by -a), every subcomponent of every path is visited from the top down, so include/exclude patterns get applied recursively to each subcomponent’s full name (e.g. to include /foo/bar/baz the subcomponents /foo and /foo/bar must not be excluded). The exclude patterns actually short-circuit the directory traversal stage when rsync finds the files to send. If a pattern excludes a particular parent directory, it can render a deeper include pattern ineffectual because rsync did not descend through that excluded section of the hierarchy. This is particularly important when using a trailing * rule. For instance, this won’t work:

+ /some/path/this-file-will-not-be-found
+ /file-is-included
- *

This fails because the parent directory some is excluded by the * rule, so rsync never visits any of the files in the some or some/path directories. One solution is to ask for all directories in the hierarchy to be included by using a single rule: + */ (put it somewhere before the - * rule), and perhaps use the --prune-empty-dirs option. […]

Note this part of the manual uses the syntax of the --filter (-f) option where + is like --include and - is like --exclude. The advised rule + */ may appear in your command line as --include '*/'. Quoting is very important, it prevents */ from being expanded by the shell.

For completeness this is what the manual says about the useful --prune-empty-dirs option:

-m, --prune-empty-dirs
This option tells the receiving rsync to get rid of empty directories from the file-list, including nested directories that have no non-directory children. This is useful for avoiding the creation of a bunch of useless directories when the sending rsync is recursively scanning a hierarchy of files using include/exclude/filter rules.

[…]

So your command may be

rsync -rmva html/ /media/pi/DEC6-5E68/html/ \
      --include '*/' \
      --include '.htaccess' \
      --include '*.html' \
      --include '*.php' \
      --exclude '*'

You can omit the destination (/media/pi/DEC6-5E68/html/ in your case) to make rsync only list what would be copied. This way you can verify if my command is what you need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.