I have directory loaded with thousands of sub directories:


Each subdirectory in turn has hundreds of subdirectories that I want to rsync if the first level subdirectory matches...

What I need is a way to copy/rsync only the directories that start with a given digit [1-9]...

What I think I want is basically something that would allow me to use wild cards to match

rsync -rzvvhP remotehost:/home/tmp/1* /home/tmp/

I want rsync to sync up the


directories and any child subdirectories they have but not any of the first level directories that start with a different digit...

........./4*/ etc..

What I've tried:

rsync -rzvvhP --exclude='*' --include-from=1.txt remotehost:/home/tmp/ /home/tmp/

where 1.txt contains:


When I do this with 2.txt though rsync still seems to run through all the directories that start with 1 and 3 etc...

How can I do this so that I can have one command to rsync only the directories that start with any given digit?

  • 1
    I don't know if that's your problem, but you may want to protect the asterisk from local shell expansion (before it even gets to rsync). 'remotehost:/home/tmp/1*' rather than without the single quotes.
    – user
    Feb 1, 2013 at 21:51
  • 1
    What is wrong with rsync -rzvvhP remotehost:/home/tmp/1* /home/tmp/? Feb 1, 2013 at 23:29

1 Answer 1


What you proposed should actually work:

rsync -rzvvhP remotehost:/home/tmp/1\* /home/tmp/

(You can get away with not quoting the * in most circumstances, as the pattern remotehost:/home/tmp/1\* is unlikely to match any file so it will be left alone with most shell setups.)

Your attempt with --exclude='*' failed because the first match applies, and your first match for everything (*) says to exclude.

See this guide for some general principles about rsync filters. Here, to include only directories beginning with 1 at the toplevel, and copy everything in included subdirectories, include /1 then exclude /*.

rsync -rzvvhP --include='/1' --exclude='/*' remotehost:/home/tmp/ /home/tmp/
  • rsync -rzvvhP --size-only --filter="+ /4*/" --exclude='/*' ... is what I ended up using...the issue I believe the problem was that the exclude was coming first...changing this from an include to filter works.
    – kasdega
    Feb 11, 2013 at 5:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .