2013-01-21 153 views
5

Erlang的每個文件是一個陌生的語言對我來說,這一週我一直在玩多國語言,我已經來到這裏尋求幫助的時候,現在我對Erlang和我被堵一次再次:)迭代通過目錄

基本上所有我想要做的是下面的,但在二郎:

Dim objFSO, objFile, objFolder 

Set objFSO = Server.CreateObject("Scripting.FileSystemObject") 
Set objFolder = objFSO.GetFolder(currentDirectory)) 

For Each objFile in objFolder.Files 
    do something with the file 
    do something else 
    do more stuff 
Next 

我來最接近的是:

-export([main/1]). 

main([]) -> 
find:files("c:\","*.txt", fun(F) -> { 
     File, c:c(File) 
}end). 

顯然,沒有工作,沒有什麼就像我需要它是..埠我已經嘗試了很多方法並閱讀了很多例子,但是根本找不到解決方案,也許這種語言只是不適合這種東西?

,這是需要一個escript(二郎腳本)

+3

[FileLib文件:fold_files](http://www.erlang.org/doc/man/filelib.html#fold_files-5)可能是你正在尋找的功能。 – legoscia

回答

11

這很難確切地建議你應該因爲用哪一種方法你「做什麼」僞太模糊。

對於像Erlang這樣的函數式語言來說,有兩種主要的方法迭代:mapfold

最大的問題歸結爲:你想幹什麼用的文件呢?你想總的東西了的文件(即,文件總大小什麼的),或者你想保存每個文件的一些值(即每個單獨的文件大小),或做你想要做的事文件你不關心這些文件的返回值是什麼(即重命名每個文件)?

我會很快在這裏給使用的文件列表中的每個的一個例子來自file:list_dir/1返回:

{ok, Filenames} = file:list_dir("some_directory"), 

摺疊

這裏我們總的所有文件的filesizes目錄使用lists:foldl(作爲@legoscia提到的,在這種情況下,filelib:fold_files可能是更好的選擇)

TotalSize = lists:foldl(fun(Filename,SizeAcc) -> 
       FileInfo = file:read_file_info("some_directory/" ++ Filename), 
       FileSize = FileInfo#file_info.size, 
       SizeAcc + FileSize 
      end, 0, Filenames). 

映射

在這裏,我們會得到的文件名列表與文件大小使用lists:map每個單獨的文件一起。將所得的列表將是格式= [{"somefile.txt",452}, {"anotherfile.exe",564},...]

FileSizes = lists:map(fun(Filename) -> 
       FileInfo = file:read_file_info("some_directory/" ++ Filename), 
       FileSize = FileInfo#file_info.size, 
       {Filename,FileSize} 
      end,Filenames). 

FOREACH(映射的變體)

的剛重命名的文件,但不關心記錄有關文件中的任何數據的另一種方法是證明使用lists:foreach,一般專門用於副作用編程中,你不關心的返回值,它的工作原理是lists:map,但不返回任何有用的東西(它只是返回的原子ok):

在這種情況下,我將顯示通過添加「重命名每個文件」。舊的」擴展到每個文件名:

lists:foreach(fun(Filename) -> 
        OldFile = "some_directory/" ++ Filename, 
        NewFile = OldFile ++ ".old", 
        file:rename(OldFile, NewFile), 
       end,Filenames). 

遞歸

當然,所有這些的原始版本 - 如果mapfoldforeach,或列表解析(我沒有覆蓋,但基本上都是用filter組件的map另一種變體)過於限制無論出於何種原因 - 你可以遞歸做的事情:

do_something_with_files([]) -> ok; 
do_something_with_files([CurrentFile|RestOfFiles]) -> 
    do_something(CurrentFile), 
    do_something_with_files(RestOfFiles). 

有很多方法可以做到你需要使用Erlang什麼,但不像像VB程序語言,你一定覺得有點超前到你想跟蹤或者爲了做確定什麼如何要迭代你的列表,因爲你在Erlang中受到不可變變量的限制。

注:爲了使用#file_info記錄,您將需要包括你的模塊的頂部與file.hrl文件:

-include_lib("kernel/include/file.hrl"). 
2

我最近寫了一個文件系統索引和在這裏下面,我爲您提供一個模塊,它可以遍歷一個或多個目錄,並讓您知道您想要的文件或找到的文件夾。它所做的是,它將spawn一個新的進程來處理任何內部目錄。您將提供兩個Functional Objects,一個用於處理目錄,另一個用於處理文件。

 
%% @doc This module provides the low level APIs for reading, writing, 
%% searching, joining and moving within directories. 
%% @end
-module(file_scavenger_utilities). %%% ------- EXPORTS ------------------------------------------------------------------------------- -compile(export_all). %%% ------- INCLUDES ----------------------------------------------------------------------------- %%% -------- MACROS ------------------------------------------------------------------------------ -define(IS_FOLDER(X),filelib:is_dir(X)). -define(IS_FILE(X),filelib:is_file(X)). -define(FAILED_TO_LIST_DIR(X), error_logger:error_report(["* File Scavenger Utilities Error * ", {error,"Failed to List Directory"},{directory,X}])). -define(NOT_DIR(X), error_logger:error_report(["* File Scavenger Utilities Error * ", {error,"Not a Directory"},{alleged,X}])). -define(NOT_FILE(X), error_logger:error_report(["* File Scavenger Utilities Error * ", {error,"Not a File"},{alleged,X}])). %%%--------- TYPES -------------------------------------------------------------------------------
%% @type dir() = string(). %% Must be containing forward slashes, not back slashes. Must not end with a slash %% after the exact directory.e.g this is wrong: "C:/Program Files/SomeDirectory/" %% but this is right: "C:/Program Files/SomeDirectory" %% @type file_path() = string(). %% Must be containing forward slashes, not back slashes. %% Should include the file extension as well e.g "C:/Program Files/SomeFile.pdf" %% -----------------------------------------------------------------------------------------------
%% @doc Enters a directory and executes the fun ForEachFileFound/2 for each file it finds %% If it finds a directory, it executes the fun %% ForEachDirFound/2. %% Both funs above take the parent Dir as the first Argument. Then, it will spawn an %% erlang process that will spread the found Directory too in the same way as the parent directory %% was spread. The process of spreading goes on and on until every File (wether its in a nested %% Directory) is registered by its full path. %% @end %% %% @spec new_user(dir(),funtion(),function())-> ok.

spread_directory(Dir,Top_Directory,ForEachFileFound,ForEachDirFound) when is_function(ForEachFileFound),is_function(ForEachDirFound) -> case ?IS_FOLDER(Dir) of false -> ?NOT_DIR(Dir); true -> F = fun(X)-> FileOrDir = filename:absname_join(Dir,X), case ?IS_FOLDER(FileOrDir) of true -> (catch ForEachDirFound(Top_Directory,FileOrDir)), spawn(fun() -> ?MODULE:spread_directory(FileOrDir,Top_Directory,ForEachFileFound,ForEachDirFound) end); false -> case ?IS_FILE(FileOrDir) of false -> {error,not_a_file,FileOrDir}; true -> (catch ForEachFileFound(Top_Directory,FileOrDir)) end end end, case file:list_dir(Dir) of
{error,_} -> ?FAILED_TO_LIST_DIR(Dir); {ok,List} -> lists:foreach(F,List) end end.

要測試,下面是使用:

 
E:\Applications>erl 
Eshell V5.9 (abort with ^G) 
1> Dir = "E:/Ruth". 
"E:/Ruth" 
2> TopDir = "E:/Ruth". 
"E:/Ruth" 
3> Folder = fun(Parent,F) -> io:format("\n\t~p contains Folder: ~p~n",[Parent,F]) end. 
#Fun<erl_eval.12.111823515> 
4> File = fun(Parent,F) -> io:format("\n\t~p contains File: ~p~n",[Parent,F]) end. 
#Fun<erl_eval.12.111823515> 
5> file_scavenger_utilities:spread_directory(Dir,TopDir,File,Folder).

"E:/Ruth" contains File: "e:/Ruth/Thumbs.db"   

    "E:/Ruth" contains File: "e:/Ruth/Robert Passport.pdf" 

    "E:/Ruth" contains File: "e:/Ruth/new mixtape.mp3" 

    "E:/Ruth" contains File: "e:/Ruth/Manning - Java 3d Programming.pdf" 

    "E:/Ruth" contains File: "e:/Ruth/jcrea350.zip" 

    "E:/Ruth" contains Folder: "e:/Ruth/java-e books" 

    "E:/Ruth" contains File: "e:/Ruth/Java Programming Unleashed.pdf"   

    "E:/Ruth" contains File: "e:/Ruth/Java Programming Language Basics.pdf" 

    "E:/Ruth" contains File: "e:/Ruth/java-e books/vb blackbook.pdf.pdf"