tadly
tadly

Reputation: 71

rsync: include file from excluded directory

So, I'm currently writing my own simple backup-client (based on rsync obviously) and after lots of trial and error I'm left with (hopefully) only one problem.

Source folder structure

.
├── .hidden_file.txt
├── .hidden_folder
│   └── .keep
├── regular_file.txt
└── regular_folder
    └── .keep

Backup command

As you can see, I'm trying to "simply" exclude eveything that matches regular* but explicitly include the file .keep within the regular_folder folder. That's the idea at least.

rsync --archive --relative --prune-empty-dirs <many other options> \
      --include='/data/source/regular_folder/.keep' \
      --exclude='regular*' \
      /data/source /data/target/<timestamp>

What I want

.
├── .hidden_file.txt
└── .hidden_folder
    └── .keep
└── regular_folder
    └── .keep

What I actually get

.
├── .hidden_file.txt
└── .hidden_folder
    └── .keep

I obviously did my fair share of googeling, man-page reading but either something obvious must have slipped me or... I don't know.

I understand that in my scenario I'd have to additionally --include='/data/source/regular_folder/ (the parent directory of the file I want) but if there'd be other files alongside .keep, those would automatically be included as well which I do not want.

Thanks for the help, I really appreciate it :)

Update

Edit Ignore all that. With my new test-cases it doesn't work anymore (which makes sense as excludes should always be prior to sources. No idea why it worked with my initial tests). Back to the drawing-board :/

Original After playing with my unittests following what ams proposed (which sadly didn't work out the way I wanted it to) I thought of something else.

Instead of adding the files/folders I explicitly want via --include, I can just add them as additional sources to rsync. The new command would look like this:

rsync --archive --relative --prune-empty-dirs <many other options> \
      --exclude='regular*' \
      /data/source /data/source/regular_folder/.keep' \
      /data/target/<timestamp>

This works nicely but...

...you guessed it, there's another problem. Source don't really work with wildcards when they would have to descend into directories. Say I want to keep all .keep files, I would like to:

rsync --archive --relative --prune-empty-dirs <many other options> \
      --exclude='regular*' \
      /data/source /data/source/*/.keep' \
      /data/target/<timestamp>

Multiple * didn't work either.

The question now. Am I just to stupid to get this to work or is that impossible?

I know sources work with wildcards within a flat hierarchy. For example the following would work as source:

/some/path/*.txt

Upvotes: 4

Views: 1603

Answers (1)

ams
ams

Reputation: 25559

Try this:

--include='/data/source/regular_folder/.keep'
--exclude='regular*/**'

Basically, that excludes all the files inside regular_folder, but not the folder itself.

It does exclude subdirectories though, so .keep files at deeper levels are not going to work. If you have that then something like this ought to work:

--include='/data/source/regular_folder/.keep'
--include='/data/source/regular_folder/deeper/deeper/.keep'
--include='*/'
--exclude='regular*/**'

Or, to simply include all .keep files:

--include='.keep'
--include='*/'
--exclude='regular*/**'

The '*/' means "include all directories", but doesn't say anything about the files.

Upvotes: 4

Related Questions