File Paths in Erlang

In Erlang, we don’t have a direct equivalent to the filepath module, but we can use the filename module to handle file paths in a portable way. Here’s how we can achieve similar functionality:

-module(file_paths).
-export([main/0]).

main() ->
    % Join should be used to construct paths in a portable way.
    % It takes any number of arguments and constructs a hierarchical path from them.
    P = filename:join(["dir1", "dir2", "filename"]),
    io:format("p: ~p~n", [P]),

    % You should always use join instead of concatenating separators manually.
    % In addition to providing portability, join will also normalize paths.
    io:format("~p~n", [filename:join("dir1//", "filename")]),
    io:format("~p~n", [filename:join("dir1/../dir1", "filename")]),

    % dirname and basename can be used to split a path to the
    % directory and the file.
    io:format("Dir(p): ~p~n", [filename:dirname(P)]),
    io:format("Base(p): ~p~n", [filename:basename(P)]),

    % We can check whether a path is absolute.
    io:format("~p~n", [filename:pathtype("dir/file")]),
    io:format("~p~n", [filename:pathtype("/dir/file")]),

    Filename = "config.json",

    % Some file names have extensions following a dot.
    % We can split the extension out of such names with extension.
    Ext = filename:extension(Filename),
    io:format("~p~n", [Ext]),

    % To find the file's name with the extension removed,
    % use filename:rootname.
    io:format("~p~n", [filename:rootname(Filename)]),

    % relative_to finds a relative path between a base and a target.
    % It returns an error if the target cannot be made relative to base.
    case filename:relative_to("a/b/t/file", "a/b") of
        {ok, Rel} -> io:format("~p~n", [Rel]);
        {error, _} -> io:format("Error in relative_to~n")
    end,

    case filename:relative_to("a/c/t/file", "a/b") of
        {ok, Rel2} -> io:format("~p~n", [Rel2]);
        {error, _} -> io:format("Error in relative_to~n")
    end.

To run this program, save it as file_paths.erl and use the Erlang shell:

$ erl
1> c(file_paths).
{ok,file_paths}
2> file_paths:main().
p: "dir1/dir2/filename"
"dir1/filename"
"dir1/filename"
Dir(p): "dir1/dir2"
Base(p): "filename"
relative
absolute
".json"
"config"
"t/file"
Error in relative_to

Note that Erlang’s filename module handles paths slightly differently from Go’s filepath:

  1. filename:pathtype/1 returns relative, absolute, or volumerelative instead of a boolean.
  2. filename:relative_to/2 is used instead of Rel, and it returns {ok, RelativePath} or {error, Reason}.
  3. Erlang doesn’t have a direct equivalent to strings.TrimSuffix, but filename:rootname/1 achieves the same result for file extensions.

These differences reflect the unique characteristics and conventions of Erlang compared to Go, while still providing similar file path manipulation capabilities.

查看推荐产品

Comments powered by Disqus