erlang 如何删除整个非空目录?

yi0zb3m4  于 2022-12-08  发布在  Erlang
关注(0)|答案(4)|浏览(174)

我想清理收集资源的临时文件。file模块只有del_dir/1,它要求目录为空。但没有函数可以获取目录中的所有文件(绝对路径为”“)
源代码如下,如何改正?

delete_path(X)->
    {ok,List} = file:list_dir_all(X), %% <--- return value has no absolute path here
    lager:debug("_229:~n\t~p",[List]),
    lists:map(fun(X)->
                      lager:debug("_231:~n\t~p",[X]),
                        ok = file:delete(X)
                end,List),
    ok = file:del_dir(X),
    ok.
jtoj6r0c

jtoj6r0c1#

你可以使用os:cmd通过控制台命令删除一个目录,虽然这是一个粗略的方法。对于类Unix操作系统,它将是:

os:cmd("rm -Rf " ++ DirPath).

如果你想用适当的Erlang函数删除一个非空目录,你必须递归地执行。下面的例子来自here,展示了如何执行:

-module(directory).
-export([del_dir/1]).

del_dir(Dir) ->
   lists:foreach(fun(D) ->
                    ok = file:del_dir(D)
                 end, del_all_files([Dir], [])).

del_all_files([], EmptyDirs) ->
   EmptyDirs;
del_all_files([Dir | T], EmptyDirs) ->
   {ok, FilesInDir} = file:list_dir(Dir),
   {Files, Dirs} = lists:foldl(fun(F, {Fs, Ds}) ->
                                  Path = Dir ++ "/" ++ F,
                                  case filelib:is_dir(Path) of
                                     true ->
                                          {Fs, [Path | Ds]};
                                     false ->
                                          {[Path | Fs], Ds}
                                  end
                               end, {[],[]}, FilesInDir),
   lists:foreach(fun(F) ->
                         ok = file:delete(F)
                 end, Files),
   del_all_files(T ++ Dirs, [Dir | EmptyDirs]).
7gs2gvoe

7gs2gvoe2#

现在,使用file:del_dir/2 API的最新版Erlang/OTP(尚未发布)可以实现这一点。
可用选项:

*递归:在删除目录本身之前递归删除目录的内容
*force:访问或删除文件或目录时忽略错误
*保持顶部:不删除最顶层的目录

来源:https://github.com/erlang/otp/pull/2565

u59ebvdq

u59ebvdq3#

Erlang中的不同方法(使用的唯一真实的原因是为了保持平台独立性):

-spec rm_rf(file:filename()) -> ok.

rm_rf(Dir) ->
    Paths = filelib:wildcard(Dir ++ "/**"),
    {Dirs, Files} = lists:partition(fun filelib:is_dir/1, Paths),
    ok = lists:foreach(fun file:delete/1, Files),
    Sorted = lists:reverse(lists:sort(Dirs)),
    ok = lists:foreach(fun file:del_dir/1, Sorted),
    file:del_dir(Dir).

上面的示例对当前目录与目标目录的关系做了一些假设--如果这对您的使用来说是个问题,建议显式设置一个工作目录并完全限定目标的路径。
值得注意的是,类似的方法也可用于递归地复制目录。

ih99xse1

ih99xse14#

自Erlang OTP 23.0起,您可以使用file:del_dir_r/1函数。

file:del_dir_r(File).

对于仍在使用旧Erlang版本的用户,这里有一个基于新的官方del_dir_r源代码的替换版本,该版本已修复,可用于旧版本:

%% Include file.hrl to have access to #file_info{} record
-include_lib("kernel/include/file.hrl").

-spec del_dir_r(File) -> ok | {error, Reason} when
      File :: file:name_all(),
      Reason :: file:posix() | badarg.

del_dir_r(File) ->
    case file:read_link_info(File) of
    {ok, #file_info{type = directory}} ->
        case file:list_dir_all(File) of
        {ok, Names} ->
            lists:foreach(fun(Name) ->
                      del_dir_r(filename:join(File, Name))
                  end, Names);
        {error, _Reason} -> ok
        end,
        file:del_dir(File);
    {ok, _FileInfo} -> file:delete(File);
    {error, _Reason} = Error -> Error
    end.

相关问题