Created
July 2, 2011 03:31
-
-
Save mrinalwadhwa/1059710 to your computer and use it in GitHub Desktop.
Erlang: list all the files in a directory and recursively in all its sub directories
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment