Skip to content

Commit 444af2e

Browse files
Add a "Find" module
1 parent 867d698 commit 444af2e

2 files changed

Lines changed: 64 additions & 3 deletions

File tree

src/Streamly/Coreutils/Find.hs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
-- |
2+
-- Module : Streamly.Coreutils.Find
3+
-- Copyright : (c) 2026 Composewell Technologies
4+
-- License : BSD-3-Clause
5+
-- Maintainer : streamly@composewell.com
6+
-- Stability : experimental
7+
-- Portability : GHC
8+
--
9+
-- List directory contents.
10+
11+
module Streamly.Coreutils.Find
12+
(
13+
find
14+
15+
-- * Options
16+
, FindOptions
17+
, recursive
18+
)
19+
where
20+
21+
import Streamly.Data.Stream.Prelude (Stream)
22+
import Streamly.FileSystem.Path (Path)
23+
24+
import qualified Streamly.Data.Stream.Prelude as Stream
25+
import qualified Streamly.Internal.Data.Stream as Stream
26+
import qualified Streamly.Internal.Data.Unfold as Unfold
27+
import qualified Streamly.Internal.FileSystem.DirIO as Dir
28+
29+
-- Note: We can also have options to follow symlinks and other dir traversal
30+
-- options once we decide on a good Configuration API.
31+
--
32+
-- XXX ls is more of a printing to console tool. We can return chunked arrays
33+
-- with newlines and short or long info in this API which are directly
34+
-- printable. In the "find" API we can return Path and structured Stat data
35+
-- instead for programmatic control.
36+
newtype FindOptions = FindOptions {findRecursive :: Bool}
37+
38+
defaultConfig :: FindOptions
39+
defaultConfig = FindOptions False
40+
41+
recursive :: Bool -> FindOptions -> FindOptions
42+
recursive opt cfg = cfg {findRecursive = opt}
43+
44+
find :: (FindOptions -> FindOptions) -> Path -> Stream IO (Either Path Path)
45+
find f dir = do
46+
case findRecursive (f defaultConfig) of
47+
False -> Dir.readEitherPaths id dir
48+
True ->
49+
-- Stream.unfoldIterateDfs unfoldOne
50+
-- BFS avoids opening too many file descriptors but may accumulate
51+
-- more data in memory.
52+
Stream.bfsUnfoldIterate unfoldOne
53+
-- $ Stream.parConcatIterate id streamOne
54+
-- $ Stream.parConcatIterate (Stream.ordered True) streamOne
55+
$ Stream.fromPure (Left dir)
56+
57+
where
58+
59+
unfoldOne = Unfold.either (Dir.eitherReaderPaths id) Unfold.nil
60+
-- streamOne = either Dir.readEitherPaths (const Stream.nil)

streamly-coreutils.cabal

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,12 @@ library
122122
, Streamly.Coreutils.Chmod
123123
, Streamly.Coreutils.Common
124124
, Streamly.Coreutils.Cp
125+
, Streamly.Coreutils.Cut
125126
, Streamly.Coreutils.Directory
126127
, Streamly.Coreutils.Dirname
127128
, Streamly.Coreutils.FileTest
129+
, Streamly.Coreutils.Find
128130
, Streamly.Coreutils.Ln
129-
, Streamly.Coreutils.Cut
130131
, Streamly.Coreutils.Ls
131132
, Streamly.Coreutils.Mkdir
132133
, Streamly.Coreutils.Mv
@@ -139,7 +140,6 @@ library
139140
, Streamly.Coreutils.Tail
140141
, Streamly.Coreutils.Touch
141142
, Streamly.Coreutils.Which
142-
, Streamly.Coreutils.FileTest.Common
143143
if os(windows)
144144
exposed-modules:
145145
Streamly.Coreutils.FileTest.Windows
@@ -148,7 +148,8 @@ library
148148
Streamly.Coreutils.FileTest.Posix
149149
, Streamly.Coreutils.Id
150150
other-modules:
151-
Streamly.Coreutils.String
151+
Streamly.Coreutils.FileTest.Common
152+
, Streamly.Coreutils.String
152153
, Streamly.Coreutils.Uniq
153154

154155
default-language: Haskell2010

0 commit comments

Comments
 (0)