turtle
turtle copied to clipboard
Feature proposal: gfind
I think having a more full featured find utility would be great.
I figured I'd post a plan to get ideas before I start trying to write it. In my head it's gfind
because it's going to implement more of the features of gnu find.
Desired Features (a start at)
- Non-recursive use
- Depth limitation like
-maxdepth
and-mindepth
- File status limitation like
-cmin
and-amin
- File type limitation like
-type
Implementation concerns
A feature rich find would have a huge number of parameters most of which wouldn't be necessary for every use. So optional arguments are almost definitely necessary. I think an approach inspired by: http://neilmitchell.blogspot.ca/2008/04/optional-parameters-in-haskell.html could be useful.
To avoid namespacing issues we could use vinyl
records, an example might look like:
gfind path (chars) ((MinDepth ==: 1) :& (MaxDepth == : 1))
A global set of defaults can be defined by the package and the users options can be integrated with the defaults via rreplace
Any thoughts and suggestions would be appreciated.
My intution is that if we design this correctly we won't need to have many parameters. Some of these desired features could be split out into orthogonal utilities. In the spirit of the Unix philosophy we want each utility to do one thing and do it well!
Specifically, I think you could split it up like this:
-
Create a
lsdepth
utility that is likelstree
except with a minimum and maximum depthlsdepth :: Int -> Int -> FilePath -> Shell FilePath
-
Structure the generalized
find
to take aShell FilePath
as an input instead of aFilePath
findtree :: Pattern a -> Shell FilePath -> Shell FilePath
This way users can customize what files to traverse by supplying
ls
,lstree
,lsdepth
, or their own hand-written directory traversal:findtree (suffix ".exe") (ls ".") -- Only search the current directory findtree (suffix ".exe") (lsdepth 0 3 ".") -- Only search three levels down
-
For file status filter, provide simple predicate functions, like:
cmin, cmax :: UTCTime -> FilePath -> Bool
Then filtering the returned files just becomes
Control.Monad.mfilter
mfilter (cmin someTime) (findtree (suffix ".exe") (ls ".")) -- Find files created after `someTime`
That seems like a better way to structure this, I'll give writing it a shot and report back.