遍历目录中的每个文件

时间:2013-01-21 16:31:42

标签: erlang

对我来说,erlang是一种奇怪的语言,本周我一直在玩多种语言,我经常来这里寻求帮助,现在我正在使用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).
显然,没有工作,没有像我需要的那样......但我已经尝试了很多方法并阅读了很多例子,但是根本无法找到解决方案,也许这种语言并不适用于这种东西?< / p>

这需要作为escript(erlang脚本)

2 个答案:

答案 0 :(得分:10)

很难确切地推荐你应该使用哪种方法,因为你的“做某事”伪代码太模糊了。

有两种主要方法可以迭代Erlang等函数式语言中的某些内容:mapfold

最大的问题归结为:你想对这些文件做什么?你想要为文件总结一些东西(即总文件大小或其他东西),或者你想为每个文件存储一些值(即每个文件大小单独)或者你想做什么到< / em>文件,你不关心这些文件的返回值是什么(即重命名每个文件)?

我将使用file:list_dir/1返回的文件列表快速给出每个示例:

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

<强>折叠

在这里,我们将使用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). ):

在这种情况下,我将通过在每个文件名中添加“.old”扩展名来重命名每个文件:

map

<强>递归

当然,所有这些的原始版本 - 如果foldforeachmap或列表推导(我没有涵盖,但基本上是另一种变体)带有filter组件的do_something_with_files([]) -> ok; do_something_with_files([CurrentFile|RestOfFiles]) -> do_something(CurrentFile), do_something_with_files(RestOfFiles). 因任何原因而限制太多 - 您可以递归地执行操作:

#file_info

有很多方法可以用Erlang做你需要的东西,但与像VB这样的过程语言不同,你必须先考虑想要跟踪或做的以确定你希望迭代你的列表,因为你受到Erlang中不可变变量的限制。

注意:要使用-include_lib("kernel/include/file.hrl"). 记录,您需要在模块顶部包含file.hrl文件:

{{1}}

答案 1 :(得分: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"