Как правильно сопоставить имена файлов в подкаталогах?
В настоящее время я изучаю книгу " Real World Haskell", и в одном упражнении из этой книги читателю предлагается реализовать сопоставление имен файлов с использованием **
, который так же, как *
, но также просматривает все подкаталоги в файловой системе. Ниже приведен фрагмент моего кода с комментариями (в данный момент много дублирования), а далее вы можете найти дополнительную информацию о коде. Я думаю, что размещенного кода достаточно для решения проблемы, и нет необходимости перечислять всю программу здесь.
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
это имя функции, отрывок которой я разместил.
Почему это не работает?
Когда я передаю только имя файла, программа ищет его только в текущем каталоге и подкаталогах первого уровня. Когда я передаю полный путь, он ищет только в указанном каталоге. Это похоже на случай (dirName, baseName)
неправильно рекурсивно Я уже некоторое время смотрю на код и не могу понять, в чем проблема.
Заметка
Если потребуется дополнительная информация, пожалуйста, дайте мне знать в комментариях, и я добавлю все, что необходимо к вопросу.
1 ответ
Вот проблема:
contents <- getDirectoryContents dirName
subDirs <- filterM doesDirectoryExist contents
getDirectoryContents
возвращает только конечные имена каталогов, так что вы должны предварять dirName
(вместе с /
) к элементам contents
перед звонком doesDirectoryExist
,