我有以下代码:
find_info(File) ->
case file:read_file_info(File) of
{ok, Facts} ->
case Facts#file_info.type of
directory -> directory;
regular -> regular
end;
{error,Reason} -> exit(Reason)
end.
find_files(Dir,Flag,Ending,Acc) ->
case file:list_dir(Dir) of
{ok,A} -> find_files_helper(A,Dir,Flag,Acc,Ending);
{_,_} -> Acc
end.
find_files_helper([H|Tail],Dir,Flag,Acc,Ending) ->
A = find_info(filename:absname_join(Dir,H)),
case A of
directory ->
case Flag of
true ->
find_files(filename:absname_join(Dir,H),Flag,Ending,Acc ++ find_files_helper(Tail,Dir,Flag,Acc,Ending));
false -> find_files_helper(Tail,Dir,Flag,Acc,Ending)
end;
regular ->
case filename:extension(H) of
Ending -> find_files_helper(Tail,Dir,Flag,[to_md5_large(H)] ++ Acc, Ending);
_ -> find_files_helper(Tail,Dir,Flag,Acc,Ending)
end;
{error,Reason} -> exit(Reason)
end;
find_files_helper([],_,_,Acc,_) -> Acc.
但是每当我运行find_files / 4时,程序只会在崩溃之前深入一个文件。 说我有以下目录
home/
a/
ser.erl
b/
c/
file.erl
file2.erl
运行后,我会得到file.erl
file2.erl
和ser.erl
的md5。但是,如果目录如下所示:
home/
a/
ser.erl
back.erl
b/
c/
file.erl
file2.erl
然后整个程序崩溃了。我花了好几个小时在我的逻辑中寻找我所缺少的东西,但我不知道。
我得到的错误消息是函数p:to_md5_large / 1中的异常enoent。
如果这里需要md5,那就是:
to_md5_large(File) ->
case file:read_file(File) of
{ok, <<B/binary>>} -> md5_helper(B,erlang:md5_init());
{error,Reason} -> exit(Reason)
end.
md5_helper(<<A:4/binary,B>>,Acc) -> md5_helper(B,erlang:md5_update(Acc,A));
md5_helper(A,Acc) ->
B = erlang:md5_update(Acc,A),
erlang:md5_final(B).
答案 0 :(得分:1)
有一个功能可以帮到你:
fold_files(Dir, RegExp, Recursive, Fun, AccIn) -> AccOut
在你的情况下:
Result = filelib:fold_files(Dir, ".*\.erl", true, fun(X,Acc) -> {ok,B} = file:read_file(X), [erlang:md5(B)|Acc] end, []).
<强> [编辑] 强>
@Bula:
由于两个原因,我没有直接回答你的问题:
第一个是,在我写答案的时候,你没有提供你得到的错误类型。使用任何语言学习如何从错误报告中获取信息非常重要。在erlang中,大多数情况下,您会将错误类型设置为发生的行,查看文档,您将获得有关出错的非常有用的信息。顺便说一下,除非你想管理错误,否则我不鼓励你写下这样的话:
case file:read_file(File) of
{ok, <<B/binary>>} -> md5_helper(B,erlang:md5_init());
{error,Reason} -> exit(Reason)
end.
以下代码将执行相同的操作,更短,并且您将获得有问题的确切行号(它不是代码中的最佳示例,但它更短)
{ok, <<B/binary>>} = file:read_file(File),
md5_helper(B,erlang:md5_init()),
我不明白为什么你想要一个“部署”版本的代码,但我建议你另一个版本,我试图遵循我的建议(直接在shell中编写,所以它需要R17 +来定义递归匿名函数):o)
1> F = fun F(X,D,Ending) ->
1> {ok,StartD} = file:get_cwd(), %% save current directory
1> ok = file:set_cwd(D), %% move to the directory to explore
1> R = case filelib:is_dir(X) of
1> true -> %% if the element to analyze is a directory
1> {ok,Files} = file:list_dir(X), %% getits content
1> [F(Y,X,Ending) || Y <- Files]; %% and recursively analyze all its elements
1> false ->
1> case filelib:is_regular(X) andalso (filename:extension(X) == Ending) of
1> true -> %% if it is a regular file with the right extension
1> {ok,B} = file:read_file(X), %% read it
1> [erlang:md5(B)]; %% and calculate the md5 (must be return in a list
1> %% for consistancy with directory results)
1> false ->
1> [] %% in other cases (symlink, ...) return empty
1> end
1> end,
1> ok = file:set_cwd(StartD), %% restore current directory
1> lists:flatten(R) %% flatten for nicer result
1> end.
#Fun<erl_eval.42.90072148>
2> Md5 = fun(D) -> F(D,D,".erl") end.
#Fun<erl_eval.6.90072148>
3> Md5("C:/My programs/erl6.2/lib/stdlib-2.2").
[<<150,238,21,49,189,164,184,32,42,239,200,52,135,78,12,
112>>,
<<226,53,12,102,125,107,137,149,116,47,50,30,37,13,211,243>>,
<<193,114,120,24,175,27,23,218,7,169,146,8,19,208,73,255>>,
<<227,219,237,12,103,218,175,238,194,103,52,180,132,113,
184,68>>,
<<6,16,213,41,39,138,161,36,184,86,17,183,125,233,20,125>>,
<<23,208,91,76,69,173,159,200,44,72,9,9,50,40,226,27>>,
<<92,8,168,124,230,1,167,199,6,150,239,62,146,119,83,36>>,
<<100,238,68,145,58,22,88,221,179,204,19,26,50,172,142,193>>,
<<253,79,101,49,78,235,151,104,188,223,55,228,163,25,16,
147>>,
<<243,189,25,98,170,97,88,90,174,178,162,19,249,141,94,60>>,
<<237,85,6,153,218,60,23,104,162,112,65,69,148,90,15,240>>,
<<225,48,238,193,120,43,124,63,156,207,11,4,254,96,250,204>>,
<<67,254,107,82,106,87,36,119,140,78,216,142,66,225,8,40>>,
<<185,246,227,162,211,133,212,10,174,21,204,75,128,125,
200,...>>,
<<234,191,210,59,62,148,130,187,60,0,187,124,150,213,...>>,
<<199,231,45,34,185,9,231,162,187,130,134,246,54,...>>,
<<157,226,127,87,191,151,81,50,19,116,96,121,...>>,
<<15,59,143,114,184,207,96,164,155,44,238,...>>,
<<176,139,190,30,114,248,0,144,201,14,...>>,
<<169,79,218,157,20,10,20,146,12,...>>,
<<131,25,76,110,14,183,5,103,...>>,
<<91,197,189,2,48,142,67,...>>,
<<94,202,72,164,129,237,...>>,
<<"^NQÙ¡8hÿèkàå"...>>,<<"ðÙ.Q"...>>,
<<150,101,76,...>>,
<<"A^ÏrÔ"...>>,<<"¹"...>>,<<...>>|...]
4>
答案 1 :(得分:1)
您收到enoent
,因为当您不在back.erl
所在的目录中时,您会将to_md5_large
等文件名传递给back.erl
。尝试传递完整的文件名。您已经在filename:absname_join(Dir,H)
中调用了find_files_helper
,因此只需将其保存到变量中,然后将该变量而不是H
传递给to_md5_large
。