5

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).

显然,不工作,也没有像我需要的那样......但我已经尝试了很多方法并阅读了很多示例,但根本无法找到解决方案,也许语言不适合这种东西?

这需要作为 escript(erlang 脚本)

4

2 回答 2

11

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

有两种主要的方法,一种是在像 Erlang 这样的函数式语言中迭代一个列表:mapfold.

最大的问题归结为:您想对这些文件做什么?您是要对文件进行汇总(即总文件大小或其他内容),还是要为每个文件存储一些值(即每个文件大小单独),还是要对文件做一些事情然后您不在乎这些文件的返回值是什么(即重命名每个文件)?

我将使用从以下位置返回的文件列表快速给出每个示例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,但不返回任何有用的东西(它只返回 atom ok):

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

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

递归

当然,所有这些的原始版本 - if mapfoldforeach或列表推导(我没有介绍,但基本上是map带有filter组件的另一种变体)无论出于何种原因都过于限制 - 你可以递归地做事情:

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").
于 2013-01-22T00:10:51.837 回答
2

我最近写了一个文件系统索引器,在下面,我为您提供了一个模块,它可以遍历一个目录,并让您使用它找到的文件或它找到的文件夹来满足您的任何需求。它的作用是spawn处理任何内部目录的新进程。您将提供两个Functional Objects,一个处理目录,另一个处理文件。

%% @doc 这个模块提供了用于读取、写入、
%% 在目录中搜索、加入和移动。
%% @结尾
-模块(file_scavenger_utilities)。 %%% -------- 出口 ---------------------------------------- -------------------------------------- -编译(export_all)。 %%% -------- 包括 ---------------------------------------- -------------------------------------- %%% -------- 宏 -------------------------- -------------------------------------- -定义(IS_FOLDER(X),文件库:is_dir(X))。 -定义(IS_FILE(X),文件库:is_file(X))。 -定义(FAILED_TO_LIST_DIR(X), error_logger:error_report([" * File Scavenger Utilities Error * ", {error,"无法列出目录"},{directory,X}]))。 -定义(NOT_DIR(X), error_logger:error_report([" * File Scavenger Utilities Error * ", {error,"不是目录"},{alleged,X}]))。 -定义(NOT_FILE(X), error_logger:error_report([" * File Scavenger Utilities Error * ", {错误,“不是文件”},{被指控,X}]))。 %%%--------- 类型 ------------------------- ------------------------------------------
%% @type dir() = string(). %% 必须包含正斜杠,而不是反斜杠。不能以斜线结尾 %% 在确切目录之后。例如这是错误的:“C:/Program Files/SomeDirectory/” %% 但这是正确的:“C:/Program Files/SomeDirectory” %% @type 文件路径() = 字符串()。 %% 必须包含正斜杠,而不是反斜杠。 %% 还应包括文件扩展名,例如“C:/Program Files/SomeFile.pdf” %%------------------------------------------------ -----------------------------------------------------------
%% @ doc 进入一个目录并为它找到的每个文件执行有趣的 ForEachFileFound/2 %% 如果它找到一个目录,它会执行有趣的 %% ForEachDirFound/2。 %% 上面的两个函数都将父目录作为第一个参数。然后,它会产生一个 %% erlang 进程也会以与父目录相同的方式传播找到的目录 %% 被传播。传播过程一直持续到每个文件(无论是在嵌套 %% Directory) 通过其完整路径注册。 %% @结尾 %% %% @spec new_user(dir(),function(),function())-> 好的。

spread_directory(目录,Top_Directory,ForEachFileFound,ForEachDirFound) 当 is_function(ForEachFileFound),is_function(ForEachDirFound) -> 案例 ?IS_FOLDER(Dir) 的 假-> ?NOT_DIR(Dir); 真-> F = 乐趣(X)-> FileOrDir = 文件名:absname_join(Dir,X), 案例 ?IS_FOLDER(FileOrDir) 的 真-> (catch ForEachDirFound(Top_Directory,FileOrDir)), 产卵(乐趣()-> ?MODULE:spread_directory(FileOrDir,Top_Directory,ForEachFileFound,ForEachDirFound) 结尾); 假-> 案例 ?IS_FILE(FileOrDir) 的 假-> {错误,not_a_file,FileOrDir}; true -> (catch ForEachFileFound(Top_Directory,FileOrDir)) 结尾 结尾 结尾, 案例文件:list_dir(Dir) of
{error,_} -> ?FAILED_TO_LIST_DIR(Dir); {ok,List} -> 列表:foreach(F,List) 结尾 结尾。

为了测试它,下面是用法:

E:\应用程序>erl
Eshell V5.9(使用 ^G 中止)
1> 目录 =“E:/露丝”。
“E:/露丝”
2> TopDir =“E:/露丝”。
“E:/露丝”
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"

于 2013-01-22T07:03:45.837 回答