And just to close out the example more fully for @chalybeum, since he said he 
was a beginning programmer, he could probably start from the code below (after 
a `nimble install 'cligen@#head'`) to do whatever it was he wanted to six 
months ago if he even stuck with programming, with Nim and/or this forum: 
    
    
    import sets, posix, cligen/[dents, statx, posixUt]
    proc chalybeum(prunePath="", recurse=0, chase=false,
                  xdev=false, roots: seq[string]) =
      ## ``prunePath`` file fmt is one base name per line.
      var prune: HashSet[string]
      for line in lines(prunePath): prune.incl line
      for root in roots:
        forPath(root, recurse, false, chase, xdev, depth,
                path, nameAt, ino, dt, lst, st, recFail):
          case errno
          of EXDEV, ENOTDIR: discard # Expected sometimes
          of EMFILE, ENFILE: return  # Too deep;Stop recurse
          else:
            let m = "chalybeum: \"" & path & "\")"
            perror cstring(m), m.len
        do:
          echo path # chalybeum logic on `path` goes here
        do: # Pre-recurse: skip dirs w/base names in prune
          if dt == DT_DIR and path[nameAt..^1] in prune:
            continue
        do: # Post-recurse; only `path` valid now
          if recFail: echo "did not recurse into ", path
    when isMainModule:
      import cligen; cligen.dispatch(chalybeum)
    
    
    Run

Replacing HashSet checking with regex prunes/excludes is not so hard. It is 
fast, does avoid symlink infinite loops (when optionally chasing), and 
conditionally avoids cross-device links which is kind of the standard set of 
Unix tree walk functionality, BUT I totally admit it's not a very easy to use 
programming interface. The logic of the recursive loop leaks out plenty. I just 
threw it together. I'm not sure it's much better than the example expanded 
recursion code would be. Maybe a little.

Reply via email to