absolute_file_name/[2,3]

Synopsis

absolute_file_name(+RelFileSpec, -AbsFileName)

absolute_file_name(+RelFileSpec, +Options, -AbsFileName)

absolute_file_name(+RelFileSpec, +Options, *AbsFileName)

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

Arguments


RelFileSpec file_spec
A valid file specification.
AbsFileName atom
The first absolute filename derived from RelFileSpec that satisfies the access modes given by Options.
Options list
A list of zero or more of the following:

ignore_underscores(Bool)
Bool =

true
When constructing an absolute filename that matches the given access modes, two names are tried: First the absolute filename derived directly from RelFileSpec, and then the filename obtained by first deleting all underscores from RelFileSpec.
false
(default) Suppresses any deletion of underscores.

extensions(Ext)
Has no effect if RelFileSpec contains a file extension. Ext is an atom or a list of atoms, each atom representing an extension that should be tried when constructing the absolute filename. The extensions are tried in the order they appear in the list. Default value is Ext = [''], i.e. only the given RelFileSpec is tried, no extension is added. To specify extensions('') or extensions([]) is equal to not giving any extensions option at all.
file_type(Type)
Has no effect if RelFileSpec contains a file extension. 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. Type must be one of the following atoms:

text
implies extensions(['']).

RelFileSpec is a file without any extension. (Default)

prolog
implies extensions(['pl','']).

RelFileSpec is a Prolog source file, maybe with a .pl extension.

object
implies extensions(['o',''])

(substitute the actual object file extension for o) RelFileSpec is a foreign language object file, maybe with an extension.

executable
implies extensions(['so',''])

(substitute the actual shared object file extension for so) RelFileSpec is a foreign executable (shared object file), maybe with an extension.

qof
implies extensions(['qof','']).

RelFileSpec is a Prolog object code file, maybe with a .qof extension.

directory
implies extensions(['']).

RelFileSpec is a directory, not a regular file. Only when this option is present can absolute_file_name/3 access directories without raising an exception.

foreign
implies extensions(['o',''])

(substitute the actual object file extension for o) Same as object. Included for backward compatibility. Might be removed from future releases.


ignore_version(Bool)
This switch has no effect on systems where files don't have version numbers. Bool =

true
When looking for a file that obeys the specified access modes, the version numbers will be ignored. The returned absolute filename will not contain any version number. To find a filename that includes a proper version number, use absolute_file_name/3 with the returned file as input, and the option ignore_version(false).

See description of access option.

false
(default) Version numbers are significant.

access(Mode)
Mode must be one of the following:

read
AbsFileName must be readable.
write
If AbsFileName exists, it must be writable. If it doesn't exist, it must be possible to create.
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.
none
(default) The file system is not accessed. The first absolute filename that is derived from RelFileSpec is returned. Note that if this option is specified, no existence exceptions can be raised.
list of access modes
A list of one or more of the above options. If AbsFile exists, it 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 to absolute_file_name/3.

Please note: The following only applies to file systems with version numbered files. If the user explicitly has specified a version number, only that version is considered. If no version number is supplied, the version number of AbsFileName is determined by:

read
newest readable version.
write
the file exists, the newest version plus one. If the file doesn't exist, a system dependent "youngest" version number.
append
If the file exists, the newest version. If the file doesn't exist, a system dependent "youngest" version number.
exist
newest version.
none
A system dependent "youngest" version number. Note that this can be switched of with the ignore_version option.
list of modes
newest version.

file_errors(Val)
Val =

error
(default) Raise an exception if a file derived from RelFileSpec 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.
fail
Fail if a file derived from RelFileSpec 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. Note that the effect of this option is the same as having the Prolog flag fileerrors set to off.

solutions(Val)
i'Val' =

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

Description

We can restrict our description to absolute_file_name/3, because absolute_file_name/2 can be defined as:

     absolute_file_name(RelFileSpec, AbsFileName) :-
        Options = [ ignore_underscores(true),
                    file_type(prolog),
                    access(exist),
                    file_errors(fail) ],
        (  absolute_file_name(RelFileSpec,
                              Options,
                              AbsFileName)
        -> true
        ;  absolute_file_name(RelFileSpec,
                              [],
                              AbsFileName)
        ).
     

Note that the semantics of absolute_file_name/2 has changed slightly since previous releases. The difference is that absolute_file_name/2 now always succeeds and returns an absolute filename, also when the RelFileSpec is a compound term. For instance, if the relative filename is library(strings), you get an absolute filename, even if the library file strings.pl doesn't exist. In previous releases, this would have raised an exception. If it's important that an error is raised when the file doesn't exist, absolute_file_name/3 with option access(exist) can be used.

Four phase process: The functionality of absolute_file_name/3 is most easily described as a four 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. Underscore deletion
  3. Extension expansion
  4. Access checking

Each of the three first 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, unifies AbsFileName with the filename, and succeeds determinately. For a thorough description, see below.

Note that the relative filename RelFileSpec may also be of the form PathAlias(FileSpec), in which case the absolute filename of the file FileSpec in one of the directories designated by PathAlias is returned (see the description of each phase below, and ref-fdi-fsp).

Description of each phase

(Phase 1) This phase translates the relative file specification given by RelFileSpec into the corresponding absolute filename.

If RelFileSpec is a term with one argument, it is interpreted as PathAlias(FileSpec) and outfile becomes the file as given by file_search_path/2. If file_search_path/2 has more than one solution, outfile is unified with the solutions in the order they are generated. If the succeeding phase fails, and there is no more solutions, an existence exception is raised.

If RelFileSpec = '', outfile is unified with the current working directory. If absolute_file_name/3 is called from a goal in a file being loaded, the directory containing that file is considered current working directory. If the succeeding phase fails, an existence exception is raised.

If RelFileSpec is an atom, other than '', it's divided into components. A component are defined to be those characters:

  1. Between the beginning of the filename and the end of the filename if there are no /s in the filename.
  2. Between the beginning of the filename and the first /.
  3. Between any two successive /-groups (where a /-group is defined to be a sequence of one or more /s with no non-/ character interspersed.)
  4. Between the last / and the end of the filename.

To give the absolute filename, the following rules are applied to each component of RelFileSpec:

  1. The component ~user, if encountered as the first component of RelFileSpec, is replaced by the absolute name of the home directory of user. If user doesn't exist, a permission exception is raised.
  2. The component ~, if encountered as the first component of RelFileSpec, is replaced by the absolute name of the home directory of the current user.
  3. If neither (1) nor (2) applies, then RelFileSpec is prefixed with the current working directory. If absolute_file_name/3 is called from a goal in a file being loaded, the directory containing that file is considered current working directory.
  4. The component . is deleted.
  5. The component .. is deleted together with the directory name syntactically preceding it. For example, a/b/../c is rewritten as a/c.
  6. Two or more consecutive /s are replaced with one /.

When these rules have been applied, the absolute filename is unified with outfile. If the succeeding phase fails, an existence exception is raised.

(Phase 2) See ignore_underscores option.

(Phase 3) See extensions and file_type options.

(Phase 4) See access option.

Exceptions


domain_error
Options contains an undefined option.
instantiation_error
Any of the Options arguments or RelFileSpec is not ground.
type_error
In Options or in RelFileSpec.
existence_error
RelFileSpec is syntactically valid but does not correspond to any file.
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.

Note that the default behavior of absolute_file_name/3, that is when Options = [], does not mimic the behavior of absolute_file_name/2.

If absolute_file_name/3 succeeds, and the file access option was one of {read, write, append}, it is guaranteed 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.

Note that absolute_file_name/3 signals a permission error if a specified file refers to a directory (unless the option access(none) is given.)

absolute_file_name/[2,3] is sensitive to the fileerrors flag, which causes the predicate to fail rather than raising permission errors when reading files with wrong permission. This has the effect that the search space always is exhausted.

directives in the extensions list. This causes the so specified access mode to be used as default access mode from there on, and the subsequently generated file names will thus be tried for this access mode, and not the default set by the access option. This can be particularly useful when used in combination with the fileerrors flag mentioned above. }

If RelFileSpec contains a .. component, the constructed absolute filename might be wrong. This occurs if the parent directory is not the same as the directory preceding .. in the relative file name, which only can happen if a soft link is involved.

Examples

To check whether the file my_text exists in the current user directory, with one of the extensions text or txt, and is both writable and readable:

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

To check if the Prolog file same_functor exists in some library, and also check if it exists under the name samefunctor:

     absolute_file_name(library(same_functor),
                        [file_type(prolog), access(exist),
                         ignore_underscores(true)],
                        File).
     

See Also

file_search_path/2, library_directory/2 nofileerrors/0, fileerrors/0, prolog_flag/[2,3]

library(files) library(directory)