Files
go_goutils/iox/fsx/funcs.go
T
brent saner 4e7d474fb3 v1.17.1
FIXED:
* tplx/sprigx would throw errors on dnsx.IsPtr, because it returns a
  bool and net.IP instead of a boolen and optional error. Fixed by
  adding dnsx.IsPtrChk and using that instead.
2026-08-08 00:13:34 -04:00

103 lines
3.1 KiB
Go

package fsx
import (
"go/types"
"io/fs"
"path/filepath"
)
/*
FsPaths returns all paths in [io/fs.FS] `fsys`.
If `fsys` is nil, both `fsPaths` and `err` will be nil.
`t` should be an OR'd [io/fs.FileMode] containing all filetypes that should be included.
Use [io/fs.ModeType] to match any non-regular-file object, or 0 to explicitly match regular files.
If `t` is non-zero but you wish to ALSO include regular files, then specify `inclFiles` as true.
(`inclFiles` is ignored if `t` == 0, as this inherently matches regular files only/explicitly.)
See [HasType] for more information on this filtering.
`maxDepth` can be used to limit recursion depth.
- If `maxDepth` == 0, only direct [io/fs.DirEntry] descendants of `fsys`
will be included in `fsPaths`.
- If `maxDepth` < 0, ALL [io/fs.DirEntry] descendants of `fsys`
will be included in `fsPaths`.
- If `maxDepth` > 0, then only children at a depth of this level or lower
("higher" in a hierarchy) will be included in `fsPaths`.
*/
func FsPaths(fsys fs.FS, t fs.FileMode, inclFiles bool, maxDepth int) (fsPaths map[string]fs.DirEntry, err error) {
var idx int
var entries []fs.DirEntry
var t fs.FileMode = types.Type()
if fsys == nil {
return
}
if fsPaths, err = getEntries(fsys, t, inclFiles, maxDepth, "."); err != nil {
return
}
return
}
/*
HasType is just a convenience wrapper for:
hasType = m & t != 0
The type(s) will be explicitly extracted from `m` and `t` first.
Note that if `t` is an OR'd set of filetypes, then HasType will return true if ANY of the types
in `t` match `m`'s type (see [r00t2.io/goutils/bitmask] for more information on bitmasking).
If you wish to check if `m` is A SINGLE type, either ensure that `t` is not OR'd
(i.e. is a single fs.FileMode type) or use [IsType] instead.
*/
func HasType(m, t fs.FileMode) (hasType bool) { return m.Type()&t.Type() != 0 }
/*
IsType is just a convenience wrapper for:
isType = m & t == t
The type(s) will be explicitly extracted from `m` and `t` first.
Note that if `t` is an OR'd set of filetypes, then IsType will *never* return true
as its type is single-valued/not bitmasked (see [r00t2.io/goutils/bitmask] for more information
on bitmasking).
If you wish to check if `m` is ONE OF multiple types in `t`, use [HasType] instead.
*/
func IsType(m, t fs.FileMode) (isType bool) { return m&t == t }
/*
getEntries is used to recursively fetch entries from `fsys`.
It mostly serves as the recursion for [FsPaths], and the arguments
retain their exact meaning except that it requires `relPath`
and `maxDepth` (if > 0) will be decremanted in each recursion.
*/
func getEntries(fsys fs.FS, t fs.FileMode, inclFiles bool, maxDepth int, relPath string) (fsPaths map[string]fs.DirEntry, err error) {
var idx int
var p string
var e []fs.DirEntry
var subs map[string]fs.DirEntry = make(map[string]fs.DirEntry)
if e, err = fs.ReadDir(fsys, relPath); err != nil {
return
}
for idx = range e {
p = filepath.Join(relPath, e[idx].Name())
if e[idx].IsDir() {
if subs, err = getEntries(fsys, t, inclFiles, maxDepth, p); err != nil {
return
}
}
}
return
}