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

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.