在给定路径中查找给定字符串

时间:2014-07-26 11:33:48

标签: haskell

正如标题所述,我试图在给定路径中找到给定的字符串。这是我到目前为止所得到的:

getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents topdir = do
  names <- getDirectoryContents topdir
  let properNames = filter (`notElem` [".", ".."]) names
  paths <- forM properNames $ \name -> do
    let path = topdir </> name
    isDirectory <- doesDirectoryExist path
    if isDirectory
      then getRecursiveContents path
    else return [path]
  return (concat paths)

findInFile:: String -> FilePath -> IO Bool
findInFile needle filePath= do
  content <- readFile filePath
  return (needle `L.isInfixOf` content)

findInFolder:: (String -> Bool) -> FilePath -> String -> IO [IO Bool]
findInFolder p path needle = do
  files <- getRecursiveContents path
  return (map (findInFile needle) (filter p files))

find = findInFolder (\p -> takeExtension p `elem` [".py", ".xml", ".html"])

我可以:

*Main> findInFile "search_string" "./path/to/a/file"
True

哪个是完美的,但我不能对文件夹进行相同的搜索:

*Main> find "./path/to/a/folder" "search_string"
*Main>

在我的文件系统中,./path/to/a/file位于./path/to/a/folder下方。因此我期待同样的结果。

我做错了什么?

注意:getRecursiveContents来自real world haskell

1 个答案:

答案 0 :(得分:3)

确实有效。唯一的问题是如何打印东西。当您在ghci中键入一些表达式时,它将在该表达式上调用print。如果值的类型为IO x,则仅当具有IO实例时,它才会执行x操作并打印Show ;否则它不会打印其他信息。 find "./path/to/a/folder" "search_string"生成IO个动作列表,其中没有Show个实例。您可以获得find的结果,这也是IO操作的列表,然后执行它们:

> x <- find "./path/to/a/folder" "search_string"
> sequence x
> [True, False ...

可能你最初想在你的功能中这样做。只需进行以下更改:

findInFolder:: (String -> Bool) -> FilePath -> String -> IO [Bool]
findInFolder p path needle = do
  files <- getRecursiveContents path
  mapM (findInFile needle) (filter p files)

现在findInFolder可以按预期工作。