The basic directory scanning routine is
file_member_of_directory(
?Directory,
?FileName,
?FullName)
is true when
Directory can be an absolute filename or a relative one. FullName will be absolute if Directory is absolute, relative if Directory is relative.
We return the FileName component because that is the component on which pattern matching is generally done. We return the FullName component in order to remove from the user the burden of manipulating the (system-dependent) rules for putting together a directory name and a file name.
This predicate acts as much like a logical relation as it can. Here are some of the ways of using it:
| ?- file_member_of_directory(foo, Name, Full), write(Name=Full), nl, fail. % to enumerate members of the directory | ?- file_member_of_directory(baz, 'ugh.pl', Full). % to test whether a file 'ugh.pl' is visible in % directory 'baz', and if so return the full name | ?- file_member_of_directory(Dir, Nam, 'baz/jar.log'). % if there is a visible regular file baz/jar.log, % to return its directory in Dir and name in Nam.
file_member_of_directory/3
has two variants:
file_member_of_directory(
?FileName,
?FullName)
file_member_of_directory/3
, except that it
checks the current directory. You could obtain this effect quite
easily by calling file_member_of_directory/3
with first argument
.
, but in other operating systems the current directory is
denoted differently. This provides an operating-system-independent way of
searching the current directory. There is one other difference,
which is of great practical importance: .
is a relative
directory name, but file_member_of_directory/2
uses the absolute
name for the current directory, so that the FullName you get back will
also be absolute. See the description of absolute_file_name/2
in
the reference pages. Note the difference between calling
absolute_file_name(FileName, FullName)
and calling
file_member_of_directory(FileName, FullName)
The former will accept any filename, but the FileName
must be instantiated. The latter will only accept simple file
names with no directory component, and insists that the file must
already exist, but in return will generate FileName.
file_member_of_directory(
?Directory,
?Pattern,
?FileName,
?FullName)
file_member_of_directory/3
, except that it
filters out all the FileNames that do not match Pattern.
Pattern is an atom that may contain ?
and *
wildcards. ?
matches any character and *
matches any sequence of
characters (cf. UNIX csh(1)
and sh(1)
).
The main use
for this routine is to select files with a particular extension.
Thus,
| ?- file_member_of_directory(foo,'*.pl',Short,Full).
matches files foo/*.pl
.
To summarize, the three routines discussed so far are
file_member_of_directory([Directory, [Pattern, ]]Short, Full)
They enumerate FileName-FullName pairs one at a time: in alphabetic order, as it happens.
There is another set of three predicates finding exactly the
same solutions, but returning them as a set of FileName-FullName
pairs. We follow here the general convention that predicates that return one
"thing" have thing
in their name, and predicates that
return the set of "things" have things
in their name.
file_members_of_directory([
?Directory, [
?Pattern, ]]
?Set)
| ?- file_member_of_directory(foo, '*.pl', S, F). S = 'bat.pl', F = 'foo/bat.pl' ; S = 'fly.pl', F = 'foo/fly.pl' ; no
one would find
| ?- file_members_of_directory(foo, '*.pl', Set). Set = ['bat.pl'-'foo/bat.pl', 'fly.pl'-'foo/fly.pl']