forked from black13ua/flactags
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_utils.erl
More file actions
124 lines (93 loc) · 3.49 KB
/
Copy pathfile_utils.erl
File metadata and controls
124 lines (93 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
-module(file_utils).
-export([recursively_list_dir/1,
recursively_list_dir/2]).
% @type name() = string() | atom() | binary().
-type name() :: string() | atom() | binary().
%% API
% @spec (Dir::name()) -> {ok, [string()]} | {error, atom()}
% @equiv recursively_list_dir(Dir, false)
%
% @doc Lists all the files in a directory and recursively in all its
% sub directories. Returns {ok, Paths} if successful. Otherwise,
% it returns {error, Reason}. Paths is a list of Paths of all the
% files and directories in the input directory's subtree. The paths are not
% sorted in any order.
-spec recursively_list_dir(Dir::name()) ->
{ok, [string()]} | {error, atom()}.
recursively_list_dir(Dir) ->
recursively_list_dir(Dir, false). % default value of FilesOnly is false
% @spec (Dir::name(), FilesOnly::boolean()) -> {ok, [string()]} |
% {error, atom()}
%
% @doc Lists all the files in a directory and recursively in all its
% sub directories. Returns {ok, Paths} if successful. Otherwise,
% it returns {error, Reason}. If FilesOnly is false, Paths is a list of paths
% of all the files <b>and directories</b> in the input directory's subtree.
% If FilesOnly is true, Paths is a list of paths of only the files in the
% input directory's subtree. The paths are not sorted in any order.
-spec recursively_list_dir(Dir::name(), FilesOnly::boolean()) ->
{ok, [string()]} | {error, atom()}.
recursively_list_dir(Dir, FilesOnly) ->
case filelib:is_file(Dir) of
true ->
case filelib:is_dir(Dir) of
true -> {ok, recursively_list_dir([Dir], FilesOnly, [])};
false -> {error, enotdir}
end;
false -> {error, enoent}
end.
%% Internal
recursively_list_dir([], _FilesOnly, Acc) -> Acc;
recursively_list_dir([Path|Paths], FilesOnly, Acc) ->
recursively_list_dir(Paths, FilesOnly,
case filelib:is_dir(Path) of
false -> [Path | Acc];
true ->
{ok, Listing} = file:list_dir(Path),
SubPaths = [filename:join(Path, Name) || Name <- Listing],
recursively_list_dir(SubPaths, FilesOnly,
case FilesOnly of
true -> Acc;
false -> [Path | Acc]
end)
end).
%% Tests
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
non_existing_file_returns_error_test() ->
?assertEqual({error, enoent},
recursively_list_dir("UnUSuAalfIlEnaMe")),
ok.
non_directory_input_returns_error_test() ->
cleanup(),
file:write_file("f1.test", <<"temp test file">>),
?assertEqual({error, enotdir},
recursively_list_dir("f1.test")),
cleanup(),
ok.
simple_test() ->
cleanup(),
filelib:ensure_dir("a/b/c/"),
?assertEqual({ok, ["a/b/c", "a/b", "a"]},
recursively_list_dir("a")),
file:write_file("a/b/f.test", <<"temp test file">>),
?assertEqual({ok, ["a/b/c","a/b/f.test","a/b","a"]},
recursively_list_dir("a")),
cleanup(),
ok.
filesonly_test() ->
cleanup(),
filelib:ensure_dir("a/b/f.test"),
file:write_file("a/b/f.test", <<"hello">>),
?assertEqual({ok, ["a/b/f.test"]},
recursively_list_dir("a", true)),
cleanup(),
ok.
cleanup() ->
file:delete("f1.test"),
file:delete("a/b/f.test"),
file:del_dir("a/b/c"),
file:del_dir("a/b"),
file:del_dir("a"),
ok.
-endif.