11.3.3 absolute_file_name/[2,3] [hookable]

Synopsis

absolute_file_name(+RelFileSpec, -AbsFileName)

absolute_file_name(+RelFileSpec, -AbsFileName, +Options)

Unifies AbsFileName with the the absolute filename that corresponds to the relative file specification RelFileSpec.

Arguments

RelFileSpec
file_spec, must be ground

A valid file specification. See below for details.

AbsFileName
atom

Corresponding absolute filename.

Options
list of term, must be ground

A list of zero or more of the following. The default is the empty list:

extensions(Ext)
Has no effect if FileSpec contains a file extension. Ext is an atom or a list of atoms, each atom representing an extension (e.g. '.pl') that should be tried when constructing the absolute file name. The extensions are tried in the order they appear in the list. Default value is Ext = [”], i.e. only the given FileSpec is tried, no extension is added. To specify extensions('') or extensions([]) is equal to not giving any extensions option at all.
file_type(Type)
Picks an adequate extension for the operating system currently running, which means that programs using this option instead of extensions(Ext) will be more portable between operating systems. This extension mechanism has no effect if FileSpec contains a file extension. Type must be one of the following atoms:
text
file
implies extensions(['']). FileSpec is a file without any extension. (Default)
source
implies extensions(['.pro','.pl','']). FileSpec is a Prolog source file, maybe with a ‘.pro’ or ‘.pl’ extension.
object
implies extensions(['.po']). FileSpec is a Prolog object file.
saved_state
implies extensions(['.sav','']). FileSpec is a saved-state, maybe with a ‘.sav’ extension.
foreign_resource
FileSpec is a foreign language shared object file, maybe with a system dependent extension.
executable
FileSpec is an executable file, maybe with a system dependent extension.
directory
implies extensions(['']). This option has two effects. First, for an access option other than access(none) the file must exist and be a directory. Second, the returned file name will end in slash (/).

Only when this option is present can absolute_file_name/3 return the name of an existing directory with an access option other than access(none) without raising an exception.


glob(Glob)
Match file names against a pattern. RelFileSpec will be expanded to a directory and AbsFileName will be the absolute path to each child that matches both the Glob pattern and any other filtering option, like access/1, extensions/1, file_type/1, .... The special children . and .. will never be returned.

The Glob should be an atom specifying a glob pattern consisting of characters interpreted as follows:

  • A ‘*’ matches any sequence of zero or more characters.
  • A ‘?’ matches exactly one character.
  • A ‘{’, ‘}’, ‘[’, ‘]’ currently matches themself but are reserved for future expansion of the allowable patterns.
  • Any other character matches itself.

Please note: Currently glob pattern matching is case sensitive, even under Windows (where all expanded file names are subjected to case-normalization). This means that a pattern containing upper case Latin 1 characters or lower case non-Latin 1 characters will never match a file name under Windows. This may be corrected in the future.

With the options solutions(all) and file_errors(fail) this can be used to enumerate the contents of a directory.

access(Mode)
Mode must be an atom or a list of atoms. If a list is given, AbsFileName must obey every specified option in the list. This makes it possible to combine a read and write, or write and exist check, into one call. If AbsFileName specifies a directory and an access option other than access(none) is specified then a permission error is signaled unless file_type(directory) is also specified.

Each atom must be one of the following:

read
AbsFileName must be readable and exist.
write
append
If AbsFileName exists, it must be writable. If it doesn't exist, it must be possible to create.
exist
The file represented by AbsFileName must exist.
execute
executable
The file represented by AbsFileName must be executable and exist. This is ignored if file_type(directory) is also specified.
search
searchable
The directory represented by AbsFileName must be searchable and exist. This is ignored unless file_type(directory) is also specified.
none
The file system is not accessed to determine existence or access properties of AbsFileName. The first absolute file name that is derived from FileSpec is returned. Note that if this option is specified, no existence exceptions can be raised. (Default)

Please note: Most current file systems have complex access control mechanisms, such as access control lists (ACLs). These mechanisms makes it hard to determine the effective access permissions, short of actually attempting the file operations in question. With networked file systems it may in fact be impossible to determine the effective access rights.

Therefore, a simplified access control model is used by absolute_file_name/3 and elsewhere in SICStus.

On UNIX systems only the “classical” access control information is used, i.e. the read/write/execute “bits” for owner/group/other.

Under Windows only the “FAT” access control information is used, i.e. a file may be marked as read-only. A file is deemed executable if its extension is one of .cmd, .bat or if it is classified as an executable by the Win32 API GetBinaryType.

This may change to more faithfully reflect the effective permissions in a future release.

file_errors(Val)
fileerrors(Val)
Val is one of the following, where the default is determined by the current value of the fileerrors Prolog flag:
error
Raise an exception if a file derived from FileSpec has the wrong permissions, that is, can't be accessed at all, or doesn't satisfy the the access modes specified with the access option. This is the default if the Prolog flag fileerrors is set to its default value, on.
fail
Fail if a file derived from FileSpec has the wrong permissions. Normally an exception is raised, which might not always be a desirable behavior, since files that do obey the access options might be found later on in the search. When this option is given, the search space is guaranteed to be exhausted. This is the default if the Prolog flag fileerrors is set to off.

solutions(Val)
Val is one of the following:
first
As soon as a file derived from FileSpec is found, commit to that file. Makes absolute_file_name/3 determinate. (Default)
all
Return each file derived from FileSpec that is found. The files are returned through backtracking. This option is probably most useful in combination with the option file_errors(fail).

relative_to(FileOrDirectory)
FileOrDirectory should be an atom, and controls how to resolve relative filenames. If it is '', file names will be treated as relative to the current working directory. If a regular, existing file is given, file names will be treated as relative to the directory containing FileOrDirectory. Otherwise, file names will be treated as relative to FileOrDirectory.

If absolute_file_name/3 is called from a goal in a file being loaded, the default is the directory containing that file, accessible from the load context (prolog_load_context/2). Otherwise, the default is the current working directory.

You can use file_systems:current_directory/1 to obtain the current working directory from a goal in a file being loaded.

Description

If FileSpec is user, then AbsFileName is unified with user; this “file name” stands for the standard input or output stream, depending on context. Otherwise, unifies AbsFileName with the first absolute file name that corresponds to the relative file specification FileSpec and that satisfies the access modes given by Options.

The functionality of absolute_file_name/3 is most easily described as multi-phase process, in which each phase gets an infile from the preceding phase, and constructs one or more outfiles to be consumed by the succeeding phases. The phases are:

  1. Syntactic rewriting
  2. Pattern expansion
  3. Extension expansion
  4. Access checking

The first phase and each of the expansion phases modifies the infile and produces variants that will be fed into the succeeding phases. The functionality of all phases but the first are decided with the option list. The last phase checks if the generated file exists, and if not asks for a new variant from the preceding phases. If the file exists, but doesn't obey the access mode option, a permission exception is raised. If the file obeys the access mode option, absolute_file_name/3 commits to that solution, subject to the solutions option, and unifies AbsFileName with the file name. For a thorough description, see below.

Note that the relative file specification FileSpec may also be of the form Path(FileSpec), in which case the absolute file name of the file FileSpec in one of the directories designated by Path is returned (see the description of each phase below).

Syntactic rewriting
This phase translates the relative file specification given by FileSpec into the corresponding absolute file name. The rewrite is done wrt. the value of the relative_to option. There can be more than one solution, in which case the outfile becomes the solutions in the order they are generated. If the following phases fails, and there are no more solutions, an existence exception is raised.

FileSpec can be a file search path, e.g. library('lists.pl'). It can also refer to system properties, environment variables and the home directory of users. See ref-fdi-syn, for a description of syntactic rewriting.

Pattern expansion
If the glob/1 option was specified all matching children of the directory will be enumerated. See the glob option.
Extension expansion
See the extensions and file_type options.
Access checking
See the access option.
Final stage
As a final stage, if file_type(directory) is specified, the file is suffixed with slash. Otherwise, trailing slash will be removed except for root directories, such as ‘/’ under UNIX or ‘c:/’ under Windows.

Backtracking

Can find multiple solutions only if the solutions(all) option is used.

Exceptions

instantiation_error
Any of the Options arguments or RelFileSpec is not ground.
type_error
In Options or in RelFileSpec.
domain_error
Options contains an undefined option.
existence_error
RelFileSpec is syntactically valid but does not correspond to any file and an access option other than access(none) was given.
permission_error
RelFileSpec names an existing file but the file does not obey the given access mode.

Comments

If an option is specified more than once the rightmost option takes precedence. This provides for a convenient way of adding default values by putting these defaults at the front of the list of options. If absolute_file_name/3 succeeds, and the file access option was one of {read, write, append}, it is guaranteed1 that the file can be opened with open/[3,4]. If the access option was exist, the file does exist, but might be both read and write protected.

If file_type(directory) is not given, the file access option is other than none, and a specified file refers to a directory, then absolute_file_name/3 signals a permission error.

absolute_file_name/[2,3] is sensitive to the fileerrors Prolog flag, which determines whether the predicate should fail or raise permission errors when encountering files with the wrong permission. Failing has the effect that the search space always is exhausted. If RelFileSpec contains ‘..’ components, these are resolved by removing directory components from the pathname, not by acessing the file system. This can give unexpected results, e.g. when soft links or mount points are involved.

This predicate is used for resolving file specification by built-in predicates that open files.

Examples

To check whether the file my_text exists in the home directory, with one of the extensions ‘.text’ or ‘.txt’, and is both writable and readable:

     | ?- absolute_file_name('~/my_text', File,
                             [extensions(['.text','.txt']),
                             access([read,write])]).

To check whether the directory bin exists in the home directory:

     | ?- absolute_file_name('~/bin', Dir,
                             [file_type(directory),
                             access(exist)]).

Here Dir would get a slash terminated value, such as /home/joe/.

To list all files in the current directory:

     | ?- findall(File, absolute_file_name('.', File,
                             [glob('*'),
                             solutions(all), file_errors(fail)]), Files).

To list all directories in the parent of the current directory containing the string “sicstus”:

     | ?- findall(File, absolute_file_name('..', File,
                             [glob('*sicstus*'),file_type(directory),
                             solutions(all), file_errors(fail)]), Files).

To find a file cmd.exe in any of the “usual places” where executables are found, i.e. by looking through the PATH environment variable:

     | ?- absolute_file_name(path('cmd.exe'), File,
                             [access(exist)]).

This uses the predefined file search path path/1, ref-fdi.

See Also

file_search_path/2, prolog_load_context/2, ref-fdi, ref-lps-flg.


Footnotes

[1] To the extent that the access permissions can be precisely determined. See the access/1 option above.



Send feedback on this subject.