Есть ли какой-нибудь обходчик каталогов в Haskell?

Есть ли в Haskell рекурсивный обходчик каталогов, чтобы я мог написать что-то вроде

listing <- walkDir "/tmp"

Я не хотел бы писать свой собственный. Я могу установить некоторую зависимость от Cabal, но я хочу, чтобы она была кроссплатформенной (по крайней мере, Linux и Windows).


person Trismegistos    schedule 08.11.2012    source источник
comment
Я написал пакет dir-tree, который позволит довольно легко определить ленивый walkDir. Я бы предположил, например. с toList, предоставленным экземпляром Foldable.   -  person jberryman    schedule 10.11.2012


Ответы (4)


Вот один из способов перечислить все файлы Haskell в дереве каталогов, используя directory-tree, который не в скрытом каталоге (имя которого начинается с '.'):

import Data.Traversable (traverse)
import System.Directory.Tree (
    AnchoredDirTree(..), DirTree(..),
    filterDir, readDirectoryWith
    )
import System.FilePath (takeExtension)

listFilesDirFiltered = do
    _:/tree <- readDirectoryWith return "C:\\devmy\\code"
    traverse print $ filterDir myPred tree
    return ()
  where myPred (Dir ('.':_) _) = False
        myPred (File n _) = takeExtension n == ".hs"
        myPred _ = True

main = listFilesDirFiltered

Работает как на Windows, так и на Linux.

person Björn Lindqvist    schedule 15.11.2012
comment
Это просто конструктор, определенный в библиотеке: hackage.haskell.org/packages/archive/directory-tree/0.11.0/doc/ - person Mateusz Kowalczyk; 13.08.2013
comment
Мне нравится эта библиотека немного больше, чем принятый ответ - она ​​проще и имеет меньше зависимостей, но все же такая же мощная. Он также совместим с объективом, но не зависит от (огромной) библиотеки объективов, если вы его не используете. Вот ссылка на главную страницу взлома: directory-tree [EDIT: но не пойми меня неправильно; FilePather тоже отлично] - person Yitz; 19.08.2013

У меня есть рекурсивное определение для обхода каталога с использованием пакета filepath:

import Control.Monad
import System.Directory
import System.FilePath
import System.Posix.Files

-- | Traverse from 'top' directory and return all the files by
-- filtering out the 'exclude' predicate.
traverseDir :: FilePath -> (FilePath -> Bool) -> IO [FilePath]
traverseDir top exclude = do
  ds <- getDirectoryContents top
  paths <- forM (filter (not.exclude) ds) $ \d -> do
    let path = top </> d
    s <- getFileStatus path
    if isDirectory s
      then traverseDir path exclude
      else return [path]
  return (concat paths)
person aycanirican    schedule 23.05.2014
comment
Спасибо @StephaneRolland. - person aycanirican; 04.11.2015

http://hackage.haskell.org/package/FilePather имеет такие функции рекурсивного обхода каталогов. .

person singpolyma    schedule 08.11.2012
comment
Есть ли какой-нибудь учебник для этой библиотеки? Это не похоже на легкий. - person Trismegistos; 09.11.2012
comment
Я использовал его на github.com/singpolyma/imapmd, но использовал только документы, представленные на взлом. - person singpolyma; 09.11.2012

Пакет filemanip предоставляет мощные и элегантные функции для этого. Например, он предоставляет fold , которая будет рекурсивно вызывать вашу функцию вниз по дереву каталогов. В качестве примера я использовал его здесь для рекурсивного списка файлов в каталог, начиная с самого старого

person danza    schedule 22.05.2014
comment
@Trismegistos Есть несколько примеров в исходный код, но это, безусловно, правда, что библиотеки Haskell, как правило, недостаточно документированы с точки зрения практических советов. Я часто обнаруживаю, что получаю больше от возни с ghci, чем от чтения документации. - person Daniel Lyons; 04.11.2015