Understanding rsync's include / exclude patterns
I want to transfer N files from a remote system, using a pattern:
ssh remote ls target/
2013-08-01.mjson.gz
2014-07-04.mjson.gz
2014-07-09.mjson.gz
2014-08-12.mjson.gz
...
I only want the 2014-07*
files. My attempts so far:
rsync -a --dry-run --verbose --include="2014-07-*" remote:target .
# transfers everything
rsync -a --dry-run --verbose --include="2014-07-*" --exclude="*" remote:target .
# transfers nothing
rsync -a --dry-run --verbose --exclude="*" --include="2014-07-*" remote:target .
# transfers nothing
rsync -a --dry-run --verbose --include="*/2014-07-*" --exclude="*" remote:target .
# transfers nothing
rsync -a --dry-run --verbose --include="***/2014-07-*" --exclude="*" remote:target .
# transfers nothing
I know I can use --files-from to indicate which files exactly I want, but it's a pain to do.
I never understood how to correctly use include/exclude to do what I want. The man page states:
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.
Reading this, I presumed that if include was first, and the filename matched, then then "filename is not skipped" part would kick in. Apparently, I'm wrong.
Further down in the man page, I see:
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
Since I used --recursive
, did that cause .
to be skipped, because of the global exclude?
How do I transfer a subset of files using include and exclude patterns?
Solution 1:
While you can use include and exclude, I think this would be a simpler solution:
rsync -a --dry-run --verbose remote:'target/2014-07*' .
The reason your include/exclude variant doesn't work is that rsync never descends into the target
directory since it is excluded by the *
pattern and not matched by the include pattern (which only matches files in target
, not target
itself). For include/exclude to work you would have to do something like
rsync -a --dry-run --verbose --include=target --include='target/2014-07-*' --exclude='*' remote:target .