diff --git a/paths/consts.go b/paths/consts.go index 8a91bbc..f948b2c 100644 --- a/paths/consts.go +++ b/paths/consts.go @@ -1,20 +1,20 @@ package paths import ( - `io/fs` + "io/fs" ) // Mostly just for reference. const ( // ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular - modeDir pathMode = pathMode(fs.ModeDir) - modeSymlink pathMode = pathMode(fs.ModeSymlink) - modePipe pathMode = pathMode(fs.ModeNamedPipe) - modeSocket pathMode = pathMode(fs.ModeSocket) - modeDev pathMode = pathMode(fs.ModeDevice) - modeCharDev pathMode = pathMode(fs.ModeCharDevice) - modeIrregular pathMode = pathMode(fs.ModeIrregular) - modeAny pathMode = modeDir | modeSymlink | modePipe | modeSocket | modeDev | modeCharDev | modeIrregular + modeDir pathMode = pathMode(fs.ModeDir) + modeSymlink pathMode = pathMode(fs.ModeSymlink) + modePipe pathMode = pathMode(fs.ModeNamedPipe) + modeSocket pathMode = pathMode(fs.ModeSocket) + modeDev pathMode = pathMode(fs.ModeDevice) + modeCharDev pathMode = pathMode(fs.ModeCharDevice) + modeIrregular pathMode = pathMode(fs.ModeIrregular) + modeAnyExceptRegular pathMode = modeDir | modeSymlink | modePipe | modeSocket | modeDev | modeCharDev | modeIrregular ) // Times diff --git a/paths/funcs.go b/paths/funcs.go index fea1181..b578898 100644 --- a/paths/funcs.go +++ b/paths/funcs.go @@ -280,13 +280,15 @@ func RealPathExistsStat(path *string) (exists bool, stat os.FileInfo, err error) targetType defines what should be included in the path list. It can consist of one or more (io/)fs.FileMode types OR'd together (ensure they are part of (io/)fs.ModeType). - (You can use 0 as a shortcut to match anything/all paths. - You can also use (io/)fs.ModeType itself to match anything/all paths.) + (You can use 0 to match regular files explicitly, and/or noFiles = true to exclude them.) + + noFiles, if true, will explicitly filter out regular files from the path results. + (Normally they are *always* included regardless of targetType.) basePtrn may be nil; if it isn't, it will be applied to *base names* (that is, quux.txt rather than /foo/bar/baz/quux.txt). - pathPtrn is like ptrn except it applies to the *entire* path, + pathPtrn is like basePtrn except it applies to the *entire* path, not just the basename, if not nil (e.g. /foo/bar/baz/quux.txt, not just quux.txt). @@ -297,17 +299,22 @@ func RealPathExistsStat(path *string) (exists bool, stat os.FileInfo, err error) ageType is one or more Time* constants OR'd together to describe which timestamp type to check. (Note that TimeCreated may not match if specified as it is only available on certain OSes, - kernel versions, and filesystems. This would lead to files being excluded that may have otherwise + kernel versions, and filesystems. This may lead to files being excluded that may have otherwise been included.) (You can use TimeAny to specify any supported time.) *Any* matching timestamp of all specified (and supported) timestamp types matches, - so be judicious with your selection. + so be judicious with your selection. They are processed in order of: + + * btime (birth/creation time) (if supported) + * mtime (modification time -- contents have changed) + * ctime (OS-specific behavior; generally disk metadata has changed) (if supported) + * atime (access time) olderThan (as mentioned above) will find paths *older* than age if true, otherwise *newer*. */ func SearchFsPaths( root string, - targetType fs.FileMode, + targetType fs.FileMode, noFiles bool, basePtrn, pathPtrn *regexp.Regexp, age *time.Duration, ageType pathTimeType, olderThan bool, ) (foundPaths []string, err error) { @@ -355,14 +362,15 @@ func SearchFsPaths( } // fs object type (file, dir, etc.) - if targetType != 0 && uint(targetType) != uint(modeAny) { - if fi, outErr = d.Info(); outErr != nil { - return - } - typeMode = fi.Mode().Type() - if !typeFilter.HasFlag(bitmask.MaskBit(typeMode)) { - return - } + if fi, outErr = d.Info(); outErr != nil { + return + } + typeMode = fi.Mode().Type() + if typeMode == 0 && noFiles { + return + } + if !typeFilter.HasFlag(bitmask.MaskBit(typeMode)) { + return } // All filters passed at this point. @@ -411,9 +419,9 @@ func filterTimes(tspec times.Timespec, age *time.Duration, ageType *pathTimeType *now = time.Now() } - // ATIME - if mask.HasFlag(bitmask.MaskBit(TimeAny)) || mask.HasFlag(bitmask.MaskBit(TimeAccessed)) { - curAge = now.Sub(tspec.AccessTime()) + // BTIME (if supported) + if tspec.HasBirthTime() && (mask.HasFlag(bitmask.MaskBit(TimeAny)) || mask.HasFlag(bitmask.MaskBit(TimeCreated))) { + curAge = now.Sub(tspec.BirthTime()) if include = tfunc(&curAge); include { return } @@ -432,9 +440,9 @@ func filterTimes(tspec times.Timespec, age *time.Duration, ageType *pathTimeType return } } - // BTIME (if supported) - if tspec.HasBirthTime() && (mask.HasFlag(bitmask.MaskBit(TimeAny)) || mask.HasFlag(bitmask.MaskBit(TimeCreated))) { - curAge = now.Sub(tspec.BirthTime()) + // ATIME + if mask.HasFlag(bitmask.MaskBit(TimeAny)) || mask.HasFlag(bitmask.MaskBit(TimeAccessed)) { + curAge = now.Sub(tspec.AccessTime()) if include = tfunc(&curAge); include { return }