diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index fc24868a5..1cc673d2f 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -68,20 +68,21 @@ given as the arguments. // BackupOptions bundles all options for the backup command. type BackupOptions struct { - Parent string - Force bool - Excludes []string - ExcludeFiles []string - ExcludeOtherFS bool - ExcludeIfPresent []string - ExcludeCaches bool - Stdin bool - StdinFilename string - Tags []string - Host string - FilesFrom []string - TimeStamp string - WithAtime bool + Parent string + Force bool + Excludes []string + InsensitiveExcludes []string + ExcludeFiles []string + ExcludeOtherFS bool + ExcludeIfPresent []string + ExcludeCaches bool + Stdin bool + StdinFilename string + Tags []string + Host string + FilesFrom []string + TimeStamp string + WithAtime bool } var backupOptions BackupOptions @@ -93,6 +94,7 @@ func init() { f.StringVar(&backupOptions.Parent, "parent", "", "use this parent snapshot (default: last snapshot in the repo that has the same target files/directories)") f.BoolVarP(&backupOptions.Force, "force", "f", false, `force re-reading the target files/directories (overrides the "parent" flag)`) f.StringArrayVarP(&backupOptions.Excludes, "exclude", "e", nil, "exclude a `pattern` (can be specified multiple times)") + f.StringArrayVar(&backupOptions.InsensitiveExcludes, "iexclude", nil, "same as `--exclude` but ignores the casing of filenames") f.StringArrayVar(&backupOptions.ExcludeFiles, "exclude-file", nil, "read exclude patterns from a `file` (can be specified multiple times)") f.BoolVarP(&backupOptions.ExcludeOtherFS, "one-file-system", "x", false, "exclude other file systems") f.StringArrayVar(&backupOptions.ExcludeIfPresent, "exclude-if-present", nil, "takes filename[:header], exclude contents of directories containing filename (except filename itself) if header of that file is as provided (can be specified multiple times)") @@ -222,6 +224,10 @@ func collectRejectByNameFuncs(opts BackupOptions, repo *repository.Repository, t opts.Excludes = append(opts.Excludes, excludes...) } + if len(opts.InsensitiveExcludes) > 0 { + fs = append(fs, rejectByInsensitivePattern(opts.InsensitiveExcludes)) + } + if len(opts.Excludes) > 0 { fs = append(fs, rejectByPattern(opts.Excludes)) } diff --git a/cmd/restic/exclude.go b/cmd/restic/exclude.go index 479f8a308..35ee5f81e 100644 --- a/cmd/restic/exclude.go +++ b/cmd/restic/exclude.go @@ -88,6 +88,16 @@ func rejectByPattern(patterns []string) RejectByNameFunc { } } +// Same as `rejectByPattern` but case insensitive. +func rejectByInsensitivePattern(patterns []string) RejectByNameFunc { + for index, path := range patterns { + patterns[index] = strings.ToLower(path) + } + return func(item string) bool { + return rejectByPattern(patterns)(strings.ToLower(item)) + } +} + // rejectIfPresent returns a RejectByNameFunc which itself returns whether a path // should be excluded. The RejectByNameFunc considers a file to be excluded when // it resides in a directory with an exclusion file, that is specified by