【发布时间】:2015-10-17 12:50:42
【问题描述】:
我目前正在阅读Real World Haskell这本书,本书中的一个练习要求读者使用**实现文件名匹配,这与*相同, 但也一直在文件系统中的子目录中查找。下面是我的带有 cmets 的代码片段(目前有很多重复),再往下你可以找到有关代码的更多信息。我认为贴出的代码已经足够解决问题了,这里不需要列出整个程序。
case splitFileName pat of
("", baseName) -> do -- just the file name passed
curDir <- getCurrentDirectory
if searchSubDirs baseName -- check if file name has `**` in it
then do
contents <- getDirectoryContents curDir
subDirs <- filterM doesDirectoryExist contents
let properSubDirs = filter (`notElem` [".", ".."]) subDirs
subDirsNames <- forM properSubDirs $ \dir -> do
namesMatching (curDir </> dir </> baseName) -- call the function recursively on subdirectories
curDirNames <- listMatches curDir baseName -- list matches in the current directory
return (curDirNames ++ (concat subDirsNames)) -- concatenate results into a single list
else listMatches curDir baseName
(dirName, baseName) -> do // full path passed
if searchSubDirs baseName
then do
contents <- getDirectoryContents dirName
subDirs <- filterM doesDirectoryExist contents
let properSubDirs = filter (`notElem` [".", ".."]) subDirs
subDirsNames <- forM properSubDirs $ \dir -> do
namesMatching (dirName </> dir </> baseName) -- call the function recursively on subdirectories
curDirNames <- listMatches dirName baseName -- list matches in the passed directory
return (curDirNames ++ (concat subDirsNames)) -- concatenate results into a single list
附加信息:
pat 是我正在寻找的模式(例如 *.txt 或 C:\\A\[a-z].*)。
splitFileName 是将文件路径拆分为目录路径和文件名的函数。如果我们在pat 中仅指定一个文件名,则元组的第一个元素将为空。
如果文件名中包含**,则searchSubDirs 返回True。
listMatches 返回与目录中的模式匹配的文件名列表,用** 替换*。
namesMatching 是我发布其摘录的函数的名称。
为什么它不起作用?
当我只传递文件名时,程序只在当前目录和第一级子目录中搜索它。当我传递完整路径时,它仅在指定目录中搜索。看起来 case (dirName, baseName) 没有正确递归。我已经查看代码一段时间了,但我无法弄清楚问题出在哪里。
注意
如果需要更多信息,请在 cmets 中告诉我,我会在问题中添加任何必要的信息。
【问题讨论】:
-
//cmets 对你有用吗??? -
@ErikR 哦,我刚刚以 C# 风格添加了它们。已编辑。
标签: haskell recursion name-matching