mirror of
https://github.com/rclone/rclone.git
synced 2024-11-26 02:14:42 +01:00
filter: allow multiple --exclude-if-present flags - fixes #6219
This commit is contained in:
parent
20aaeba547
commit
f4f0e444bf
@ -2136,6 +2136,7 @@ For the filtering options
|
|||||||
* `--filter-from`
|
* `--filter-from`
|
||||||
* `--exclude`
|
* `--exclude`
|
||||||
* `--exclude-from`
|
* `--exclude-from`
|
||||||
|
* `--exclude-if-present`
|
||||||
* `--include`
|
* `--include`
|
||||||
* `--include-from`
|
* `--include-from`
|
||||||
* `--files-from`
|
* `--files-from`
|
||||||
|
@ -750,7 +750,9 @@ Useful for debugging.
|
|||||||
|
|
||||||
The `--exclude-if-present` flag controls whether a directory is
|
The `--exclude-if-present` flag controls whether a directory is
|
||||||
within the scope of an rclone command based on the presence of a
|
within the scope of an rclone command based on the presence of a
|
||||||
named file within it.
|
named file within it. The flag can be repeated to check for
|
||||||
|
multiple file names, presence of any of them will exclude the
|
||||||
|
directory.
|
||||||
|
|
||||||
This flag has a priority over other filter flags.
|
This flag has a priority over other filter flags.
|
||||||
|
|
||||||
@ -764,8 +766,6 @@ E.g. for the following directory structure:
|
|||||||
The command `rclone ls --exclude-if-present .ignore dir1` does
|
The command `rclone ls --exclude-if-present .ignore dir1` does
|
||||||
not list `dir3`, `file3` or `.ignore`.
|
not list `dir3`, `file3` or `.ignore`.
|
||||||
|
|
||||||
`--exclude-if-present` can only be used once in an rclone command.
|
|
||||||
|
|
||||||
## Common pitfalls
|
## Common pitfalls
|
||||||
|
|
||||||
The most frequent filter support issues on
|
The most frequent filter support issues on
|
||||||
|
@ -47,7 +47,7 @@ These flags are available for every command.
|
|||||||
--error-on-no-transfer Sets exit code 9 if no files are transferred, useful in scripts
|
--error-on-no-transfer Sets exit code 9 if no files are transferred, useful in scripts
|
||||||
--exclude stringArray Exclude files matching pattern
|
--exclude stringArray Exclude files matching pattern
|
||||||
--exclude-from stringArray Read exclude patterns from file (use - to read from stdin)
|
--exclude-from stringArray Read exclude patterns from file (use - to read from stdin)
|
||||||
--exclude-if-present string Exclude directories if filename is present
|
--exclude-if-present stringArray Exclude directories if filename is present
|
||||||
--expect-continue-timeout duration Timeout when using expect / 100-continue in HTTP (default 1s)
|
--expect-continue-timeout duration Timeout when using expect / 100-continue in HTTP (default 1s)
|
||||||
--fast-list Use recursive list if available; uses more memory but fewer transactions
|
--fast-list Use recursive list if available; uses more memory but fewer transactions
|
||||||
--files-from stringArray Read list of source-file names from file (use - to read from stdin)
|
--files-from stringArray Read list of source-file names from file (use - to read from stdin)
|
||||||
|
@ -86,7 +86,7 @@ type Opt struct {
|
|||||||
FilterFrom []string
|
FilterFrom []string
|
||||||
ExcludeRule []string
|
ExcludeRule []string
|
||||||
ExcludeFrom []string
|
ExcludeFrom []string
|
||||||
ExcludeFile string
|
ExcludeFile []string
|
||||||
IncludeRule []string
|
IncludeRule []string
|
||||||
IncludeFrom []string
|
IncludeFrom []string
|
||||||
FilesFrom []string
|
FilesFrom []string
|
||||||
@ -392,8 +392,10 @@ func (f *Filter) ListContainsExcludeFile(entries fs.DirEntries) bool {
|
|||||||
obj, ok := entry.(fs.Object)
|
obj, ok := entry.(fs.Object)
|
||||||
if ok {
|
if ok {
|
||||||
basename := path.Base(obj.Remote())
|
basename := path.Base(obj.Remote())
|
||||||
if basename == f.Opt.ExcludeFile {
|
for _, excludeFile := range f.Opt.ExcludeFile {
|
||||||
return true
|
if basename == excludeFile {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,12 +438,14 @@ func (f *Filter) IncludeDirectory(ctx context.Context, fs fs.Fs) func(string) (b
|
|||||||
// empty string (for testing).
|
// empty string (for testing).
|
||||||
func (f *Filter) DirContainsExcludeFile(ctx context.Context, fremote fs.Fs, remote string) (bool, error) {
|
func (f *Filter) DirContainsExcludeFile(ctx context.Context, fremote fs.Fs, remote string) (bool, error) {
|
||||||
if len(f.Opt.ExcludeFile) > 0 {
|
if len(f.Opt.ExcludeFile) > 0 {
|
||||||
exists, err := fs.FileExists(ctx, fremote, path.Join(remote, f.Opt.ExcludeFile))
|
for _, excludeFile := range f.Opt.ExcludeFile {
|
||||||
if err != nil {
|
exists, err := fs.FileExists(ctx, fremote, path.Join(remote, excludeFile))
|
||||||
return false, err
|
if err != nil {
|
||||||
}
|
return false, err
|
||||||
if exists {
|
}
|
||||||
return true, nil
|
if exists {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -34,7 +34,7 @@ func AddFlags(flagSet *pflag.FlagSet) {
|
|||||||
flags.StringArrayVarP(flagSet, &Opt.FilterFrom, "filter-from", "", nil, "Read filtering patterns from a file (use - to read from stdin)")
|
flags.StringArrayVarP(flagSet, &Opt.FilterFrom, "filter-from", "", nil, "Read filtering patterns from a file (use - to read from stdin)")
|
||||||
flags.StringArrayVarP(flagSet, &Opt.ExcludeRule, "exclude", "", nil, "Exclude files matching pattern")
|
flags.StringArrayVarP(flagSet, &Opt.ExcludeRule, "exclude", "", nil, "Exclude files matching pattern")
|
||||||
flags.StringArrayVarP(flagSet, &Opt.ExcludeFrom, "exclude-from", "", nil, "Read exclude patterns from file (use - to read from stdin)")
|
flags.StringArrayVarP(flagSet, &Opt.ExcludeFrom, "exclude-from", "", nil, "Read exclude patterns from file (use - to read from stdin)")
|
||||||
flags.StringVarP(flagSet, &Opt.ExcludeFile, "exclude-if-present", "", "", "Exclude directories if filename is present")
|
flags.StringArrayVarP(flagSet, &Opt.ExcludeFile, "exclude-if-present", "", nil, "Exclude directories if filename is present")
|
||||||
flags.StringArrayVarP(flagSet, &Opt.IncludeRule, "include", "", nil, "Include files matching pattern")
|
flags.StringArrayVarP(flagSet, &Opt.IncludeRule, "include", "", nil, "Include files matching pattern")
|
||||||
flags.StringArrayVarP(flagSet, &Opt.IncludeFrom, "include-from", "", nil, "Read include patterns from file (use - to read from stdin)")
|
flags.StringArrayVarP(flagSet, &Opt.IncludeFrom, "include-from", "", nil, "Read include patterns from file (use - to read from stdin)")
|
||||||
flags.StringArrayVarP(flagSet, &Opt.FilesFrom, "files-from", "", nil, "Read list of source-file names from file (use - to read from stdin)")
|
flags.StringArrayVarP(flagSet, &Opt.FilesFrom, "files-from", "", nil, "Read list of source-file names from file (use - to read from stdin)")
|
||||||
|
@ -81,7 +81,7 @@ func TestListDirSorted(t *testing.T) {
|
|||||||
assert.Equal(t, "sub dir/sub sub dir/", str(1))
|
assert.Equal(t, "sub dir/sub sub dir/", str(1))
|
||||||
|
|
||||||
// testing ignore file
|
// testing ignore file
|
||||||
fi.Opt.ExcludeFile = ".ignore"
|
fi.Opt.ExcludeFile = []string{".ignore"}
|
||||||
|
|
||||||
items, err = list.DirSorted(context.Background(), r.Fremote, false, "sub dir")
|
items, err = list.DirSorted(context.Background(), r.Fremote, false, "sub dir")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -98,7 +98,7 @@ func TestListDirSorted(t *testing.T) {
|
|||||||
assert.Equal(t, "sub dir/ignore dir/.ignore", str(0))
|
assert.Equal(t, "sub dir/ignore dir/.ignore", str(0))
|
||||||
assert.Equal(t, "sub dir/ignore dir/should be ignored", str(1))
|
assert.Equal(t, "sub dir/ignore dir/should be ignored", str(1))
|
||||||
|
|
||||||
fi.Opt.ExcludeFile = ""
|
fi.Opt.ExcludeFile = nil
|
||||||
items, err = list.DirSorted(context.Background(), r.Fremote, false, "sub dir/ignore dir")
|
items, err = list.DirSorted(context.Background(), r.Fremote, false, "sub dir/ignore dir")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, items, 2)
|
require.Len(t, items, 2)
|
||||||
|
@ -1309,7 +1309,7 @@ func TestOverlappingFilterCheckWithFilter(t *testing.T) {
|
|||||||
fi, err := filter.NewFilter(nil)
|
fi, err := filter.NewFilter(nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, fi.Add(false, "*/exclude/"))
|
require.NoError(t, fi.Add(false, "*/exclude/"))
|
||||||
fi.Opt.ExcludeFile = ".ignore"
|
fi.Opt.ExcludeFile = []string{".ignore"}
|
||||||
ctx = filter.ReplaceConfig(ctx, fi)
|
ctx = filter.ReplaceConfig(ctx, fi)
|
||||||
|
|
||||||
src := &testFs{testFsInfo{name: "name", root: "root"}}
|
src := &testFs{testFsInfo{name: "name", root: "root"}}
|
||||||
|
@ -1452,7 +1452,7 @@ func TestSyncOverlapWithFilter(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, fi.Add(false, "/rclone-sync-test/"))
|
require.NoError(t, fi.Add(false, "/rclone-sync-test/"))
|
||||||
require.NoError(t, fi.Add(false, "*/layer2/"))
|
require.NoError(t, fi.Add(false, "*/layer2/"))
|
||||||
fi.Opt.ExcludeFile = ".ignore"
|
fi.Opt.ExcludeFile = []string{".ignore"}
|
||||||
ctx = filter.ReplaceConfig(ctx, fi)
|
ctx = filter.ReplaceConfig(ctx, fi)
|
||||||
|
|
||||||
subRemoteName := r.FremoteName + "/rclone-sync-test"
|
subRemoteName := r.FremoteName + "/rclone-sync-test"
|
||||||
|
@ -507,10 +507,12 @@ func walkRDirTree(ctx context.Context, f fs.Fs, startPath string, includeAll boo
|
|||||||
// Check if we need to prune a directory later.
|
// Check if we need to prune a directory later.
|
||||||
if !includeAll && len(fi.Opt.ExcludeFile) > 0 {
|
if !includeAll && len(fi.Opt.ExcludeFile) > 0 {
|
||||||
basename := path.Base(x.Remote())
|
basename := path.Base(x.Remote())
|
||||||
if basename == fi.Opt.ExcludeFile {
|
for _, excludeFile := range fi.Opt.ExcludeFile {
|
||||||
excludeDir := parentDir(x.Remote())
|
if basename == excludeFile {
|
||||||
toPrune[excludeDir] = true
|
excludeDir := parentDir(x.Remote())
|
||||||
fs.Debugf(basename, "Excluded from sync (and deletion) based on exclude file")
|
toPrune[excludeDir] = true
|
||||||
|
fs.Debugf(basename, "Excluded from sync (and deletion) based on exclude file")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case fs.Directory:
|
case fs.Directory:
|
||||||
|
@ -736,13 +736,13 @@ b/c/d/
|
|||||||
e
|
e
|
||||||
`, nil, "", -1, "ign", true},
|
`, nil, "", -1, "ign", true},
|
||||||
} {
|
} {
|
||||||
fi.Opt.ExcludeFile = test.excludeFile
|
fi.Opt.ExcludeFile = []string{test.excludeFile}
|
||||||
r, err := walkRDirTree(context.Background(), nil, test.root, test.includeAll, test.level, makeListRCallback(test.entries, test.err))
|
r, err := walkRDirTree(context.Background(), nil, test.root, test.includeAll, test.level, makeListRCallback(test.entries, test.err))
|
||||||
assert.Equal(t, test.err, err, fmt.Sprintf("%+v", test))
|
assert.Equal(t, test.err, err, fmt.Sprintf("%+v", test))
|
||||||
assert.Equal(t, test.want, r.String(), fmt.Sprintf("%+v", test))
|
assert.Equal(t, test.want, r.String(), fmt.Sprintf("%+v", test))
|
||||||
}
|
}
|
||||||
// Set to default value, to avoid side effects
|
// Set to default value, to avoid side effects
|
||||||
fi.Opt.ExcludeFile = ""
|
fi.Opt.ExcludeFile = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListType(t *testing.T) {
|
func TestListType(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user