2011-07-11 72 views
14

我要的是寫一個Haskell函數當前目錄,例如如何列出當前目錄下的所有文件

改變當前目錄下的文件返回到

:cd c:/code/haskell 

然後寫它返回一個函數在一組如

[x | x <-getDirectoryContents ] 

編輯的文件:

我已經寫了一個函數某事像這樣列出文件 (參考:http://zvon.org/other/haskell/Outputdirectory/index.html

import Directory 

main = _dir "/tmp/FOO" 

_dir _path =do 
    setCurrentDirectory _path 
    _cd <- getCurrentDirectory 
    print _cd 
    _file <- getDirectoryContents _cd 
    print _file 

所以調用_dir「C:/代碼/哈斯克爾」將列出所有文件+目錄名(非遞歸)。我現在想的是把這種謂詞中的功能,例如:

[ x| x <- _dir "c:/code/haskell" | x start with 'haskell_' ] 

這樣我就可以在文件名

+0

你需要改變當前目錄? 'getDirectoryContents'將一個目錄作爲參數。 – stusmith

+0

我需要一個功能列出給定目錄下的所有文件,並致電該組謂詞中,並應用了一些過濾器,只列出滿足一定條件的名稱。由於 – sakhunzai

+10

這些下劃線是如此醜陋... – alternative

回答

19

看來你應用的過濾器正在尋找:

getDirectoryContents :: FilePath -> IO [FilePath] 

參閱:http://www.haskell.org/ghc/docs/6.12.2/html/libraries/directory-1.0.1.1/System-Directory.html#1

+0

[x | x < - getDirectoryContents :: FilePath - > IO [FilePath]]返回以下錯誤無法與實際類型爲'FilePath - > IO'的預期類型'[t0]' 匹配[文件路徑]」 ......我是新來的Haskell,請考慮我的新受 – sakhunzai

+0

@sakhunzai:嘗試''getDirectoryContents在GHCI提示‘’。如果可行,那麼瞭解一下'IO' monad。 –

+0

我貼了一個函數簽名:) ..可惜我沒有這個系統上哈斯克爾..我希望從GR8哈斯克爾社區有人會給你確切的代碼 – Ankur

5

第一點:表達式[x | x <- lst]是完全一樣lst,因此,如果lst我是一個列表,那麼這個列表理解的使用就沒有必要了。

第二:爲[x | x <-getDirectoryContents ]工作,值getDirectoryContents應該是一個列表。但事實並非如此! getDirectoryContents是一個IO值。

可以通過以下方式使用此函數(一元表達式內):

do 
    files <- getDirectoryContents "." 
    print files 

(或 - 內gh​​ci中 - 使用:do; files <- getDirectoryContents "."; print files

files具有類型[FilePath]和同時表達已鍵入IO()

+0

感謝phyinfo,就是比我好(見我的編輯)。我們可以在謂詞中編寫一個謂詞,以便我們可以對名稱應用過濾器。再次感謝您的幫助 – sakhunzai

+0

,或者在我看來,更乾淨的'getDirectoryContents'。「 >> = print' – alternative

+1

@ sakhunzai:如果你想用謂詞pred來過濾文件,你可以做以下事情:'do;文件< - getDirectoryContents;打印$ filter pred文件' – phynfo

6

如何如下:

import Data.List 
import System.Directory 

main = do all <- getDirectoryContents "/tmp/FOO" 
      let filtered = filter (isPrefixOf "haskell") all 
      print filtered 
+0

'liftM'經常清理好東西(imo):'print = << liftM(filter(isPrefixOf「haskell」))(getDirectoryContents「。」)'(編輯:但是,stusmith的代碼對於Haskeller開始理解起來更簡單) –

+0

大部分完成! 'getFiles :: String - > String - > IO() getFiles dp flt = do files < - getDirectoryContents dp; let filtered = filter(isPrefixOf flt)files print filtered'我不明白爲什麼大家都指着我直接打印文件名到控制檯。可以將文件名CAST作爲字符串獲取並將其存儲到一個變量中,並使用PRINT之外的其他函數輸出它。我的理解是,print直接將文件名作爲String數組回顯給控制檯。謝謝 – sakhunzai

5

所有你需要做的編寫返回當前目錄中的所有文件的功能如下:

import System.Directory 

filesInCurDir = getCurrentDirectory >>= getDirectoryContents 

的>> =運算符是單子測序操作員值傳遞。這裏最好描述http://www.haskell.org/tutorial/monads.html

如果你要使用這裏面ghci的:

let filesInCurDir = getCurrentDirectory >>= getDirectoryContents 

,您可以檢查該函數的類型爲filesInCurDir :: IO [FilePath]從而保持了「一元性」。

因此,如果您想進一步過濾的文件,你可以這樣做:

let filteredFilesInCurDir = 
    getCurrentDirectory >>= 
    getDirectoryContents >>= 
    \files -> return [ x | x <- files, (length x) > 10 ] 

如果你想每次通過過濾器:

let filterFilesInCurDir f = 
    getCurrentDirectory >>= 
    getDirectoryContents >>= 
    \files -> return [ x | x <- files, f x ] 

這是一樣的:

let filteredFilesInCurDir f = 
    getCurrentDirectory >>= 
    getDirectoryContents >>= 
    return . filter f 

,你可以用它喜歡:

filterFilesInCurDir (\x -> (length x) > 2) 
3

filemanip包提供了一個 更具通用性和靈活性的功能,用於此特定任務。

I.e.從給定的目錄

> :m + System.FilePath.Find 
> :t find always (fileType ==? RegularFile) 
find always (fileType ==? RegularFile) :: FilePath -> IO [FilePath] 

這個包上市規則文件是Windows兼容的(因爲它取決於unix-compat而不只是unix ),也有整齊的自我描述haddocs。

1

下面是使用Control.Applicative另一種方法:

import Control.Applicative 
import System.Directory 

isRegularFileOrDirectory :: FilePath -> Bool 
isRegularFileOrDirectory f = f /= "." && f /= ".." 

main :: IO() 
main = do 
    fileNames <- filter isRegularFileOrDirectory <$> getDirectoryContents "." 
    putStrLn $ show $ fileNames 
+0

啊完美之一,謝謝,它給了我:'getDirectoryContents「../」 [「。」,「..」,「。DS_Store」,「Clojure」,「Haskell」,「Java」,「Mobile」 ,「nll」,「Phing」]' – sakhunzai

+0

@sakhunzai:不客氣。顯然,你可以用你選擇的謂詞來替換'isRegularFileOrDirectory'。 –

相關問題