Erlang Central

Walking Directory Tree

Revision as of 02:41, 4 September 2006 by Bfulgham (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Problem

You need to look at every file in a directory, or an entire directory tree, that matches a given pattern.

Solution

wildcard function in the Erlang standard library filelib module is a very flexible way to do this. wildcard takes as input a string containing standard UNIX wild card elements (such as the *, ?, or { list-of-alternatives }) and returns a list of file names that satisfy the criteria:

% list all files and directories under /tmp
1> filelib:wildcard("/tmp/*").
["/tmp/.ICE-unix",
 "/tmp/.X11-unix",
 "/tmp/.font-unix",
 "/tmp/test1.erl",
 "/tmp/test2.erl",
 "/tmp/testB.erl",
 "/tmp/testC.erl",
 "/tmp/wings.erl"]

You can provide finer-grained control over the results by using some of the list primitives, such as filter or fold, along with various file operations and predicates to only provide results of interest to you:

% list all subdirectories of /tmp
2> lists:filter(fun(X) -> filelib:is_dir(X) end, filelib:wildcard("/tmp/*")).
["/tmp/.ICE-unix",
 "/tmp/.X11-unix",
 "/tmp/.font-unix",
 "/tmp/testC.erl"]

% list all files with extension .erl under /tmp
3> lists:filter(fun(X) -> not filelib:is_dir(X) end,
3>     filelib:wildcard("/tmp/*.erl")).
["/tmp/test1.erl","/tmp/test2.erl","/tmp/testB.erl","/tmp/wings.erl"]

% list all files under /tmp that are > 1024 bytes
4> lists:filter(fun(X) -> not filelib:is_dir(X)
4>    andalso filelib:file_size(X) > 1024 end, 
4>    filelib:wildcard("/tmp/*.erl")).
["/tmp/wings.erl"]

Discussion

The examples given all just act on metadata of the file, there's no reason you can't inspect the contents of the file in the filter function, though that will make the function much slower.