如何正确匹配子目录中的文件名?
How to properly match file names in subdirectories?
我目前正在阅读 真实世界 Haskell 这本书的一个练习要求 reader 实现文件名匹配与使用**
,与 *
相同,但也会在文件系统中一直查找子目录。下面是我的代码片段和注释(目前有很多重复),您可以在更下方找到有关该代码的其他信息。我认为发布的代码足以解决问题,没有必要在这里列出整个程序。
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
returns True
如果文件名中有 **
.
listMatches
returns 与目录中的模式匹配的文件名列表,用 **
代替 *
。
namesMatching
是我发布其摘录的函数的名称。
为什么不起作用?
当我只传递文件名时,程序只在当前目录和第一级子目录中搜索它。当我传递完整路径时,它仅在指定目录中搜索。看起来 case (dirName, baseName)
没有正确递归。我已经查看代码一段时间了,但我无法弄清楚问题出在哪里。
备注
如果需要更多信息,请在评论中告诉我,我会在问题中添加任何必要的信息。
这里有一个问题:
contents <- getDirectoryContents dirName
subDirs <- filterM doesDirectoryExist contents
getDirectoryContents
仅 returns 目录的叶名称,因此您必须将 dirName
(连同 /
)添加到 [=14 的元素之前=] 在调用 doesDirectoryExist
.
之前
我目前正在阅读 真实世界 Haskell 这本书的一个练习要求 reader 实现文件名匹配与使用**
,与 *
相同,但也会在文件系统中一直查找子目录。下面是我的代码片段和注释(目前有很多重复),您可以在更下方找到有关该代码的其他信息。我认为发布的代码足以解决问题,没有必要在这里列出整个程序。
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
returns True
如果文件名中有 **
.
listMatches
returns 与目录中的模式匹配的文件名列表,用 **
代替 *
。
namesMatching
是我发布其摘录的函数的名称。
为什么不起作用?
当我只传递文件名时,程序只在当前目录和第一级子目录中搜索它。当我传递完整路径时,它仅在指定目录中搜索。看起来 case (dirName, baseName)
没有正确递归。我已经查看代码一段时间了,但我无法弄清楚问题出在哪里。
备注
如果需要更多信息,请在评论中告诉我,我会在问题中添加任何必要的信息。
这里有一个问题:
contents <- getDirectoryContents dirName
subDirs <- filterM doesDirectoryExist contents
getDirectoryContents
仅 returns 目录的叶名称,因此您必须将 dirName
(连同 /
)添加到 [=14 的元素之前=] 在调用 doesDirectoryExist
.