Created attachment 11015 [details]
If I just pass --exclude=file or --exclude=dir to rsync, the file or dir is excluded correctly.
However, if you pass a list of files in --files-from= that includes the file I want to exclude, then only --exclude=file works as before; --exclude=dir doesn't seem to do anything at all.
As a workaround, I've found that --exclude=dir/** will actually exclude dir, as I originally wanted.
This behaviour is counter-intuitive to me; at the very least, I'd expect --exclude=dir to work the same as --exclude=file.
I've checked that the behaviour is present in latest git master. I've also included a simple reproducer script (uncomment 1 of the 4 rsync commands and run it to see the result of the transfer).
Excludes don't affect args, just items that are found in recursion. A files-from list is the same as specifying all the names as args on the command-line, and thus are not affected. Specifying an exclude of just the dir name matches only that dir itself, so when recursing inside the dir, that rule won't match anything. If you don't want a particular arg to be included, you can filter it out of the files-from file. Your exclude of dir/** (or dir/***) is also a good solve, as it tells rsync to affect the contents of a particular path.
One filter solution:
egrep -v '/dir(/|$)' files_from | rsync -aiv --files-from=- / /to/
(In reply to Wayne Davison from comment #1)
Thank you for the explanation.