Search code examples
shellsyntaxsshrsyncpatternsyntaxexception

rsync --include --exclude simple task doesn't work


I would like to use rsync to download specific files from a server, here are the scheme of the directory:

. 
file1
fakeotherfolder
   filefile
   morefile
   morefakefolder
      file
file2
file3
mainfolder
   myfolder1
      folfile1
      folfile2
   myfolder2
      folfile1
      folfile2
   myfolder3
      folfile1
      folfile2
   myfolder4
      folfile1
      folfile2

Basically I would like to get ALL the files that are NOT in a mainfolder/myfolder* except the specific mainfolder/myfolder2 for exemple.

What I want at the end:

 . 
file1
fakefolder
   filefile
   morefile
   morefakefolder
      file
file2
file3
mainfolder
   myfolder2
      folfile1
      folfile2

I tried rsync with the following options:

rsync --include="*/mainfolder/myfolder2/*" --exclude="*/mainfolder/*"

but what I get is an empty mainfolder...

 . 
file1
fakefolder
   filefile
   morefile
   morefakefolder
      file
file2
file3
mainfolder

Solution

  • What went wrong

    rsync --include="*/mainfolder/myfolder2/*" --exclude="*/mainfolder/*"
    
    1. The directive --include="*/mainfolder/myfolder2/*" tells rsync to include the files under directory */mainfolder/myfolder2/. You might think that it should implicitly tell it to include the directory */mainfolder/myfolder2/ but it doesn't. It only includes the files under that directory.

    2. The directive --exclude="*/mainfolder/*" tells it to exclude all files and directories under */mainfolder. This means that it excludes */mainfolder/myfolder2/. Because myfolder2 is excluded, the files under it will never be examined.

    How to fix it

    The solution is to explicitly include mainfolder/myfolder2:

    rsync --include="mainfolder/myfolder2" --include="mainfolder/myfolder2/*" --exclude="mainfolder/*" src/ dest
    

    The solution is to explicitly include mainfolder/myfolder2:

    Note that resync interprets includes/excludes in the order in which they are stated. Thus, it is important that --include="mainfolder/myfolder2" appears before --exclude="mainfolder/*". In sum, we need three directives and the exclude directive needs to be last:

    1. --include="mainfolder/myfolder2"

    2. --include="mainfolder/myfolder2/*"

    3. --exclude="mainfolder/*"