Is there a Prolog built-in to get the file system canonical name of a file

I tried the following in SWI-Prolog:

?- absolute_file_name('/<user>/Desktop/dict.txt', X).
X = '/<user>/Desktop/dict.txt'.

In another Prolog system I get (you can ignore the file:):

?- absolute_file_name('/<user>/Desktop/dict.txt', X).
X = 'file:/<user>/Desktop/Dict.TXT' 

This is a discrepancy on a Mac due to case insensitive file search.

Is there any option or other built-in to get the canonical name on a Mac?

Maybe the file_name_case_handling prolog flag can help you?

Also asolute_file_name needs the option access(read) or some similar option to refer to an existing file, otherwise it is representing an abstract path which may be a non existent file.

What is the output of this?

?- absolute_file_name('/<user>/Desktop/dict.txt', X,[access(read)]).

strange, on my system:

2 ?- absolute_file_name('/<user>/Desktop/dict.txt', X,[access(read)]).
ERROR: source_sink `'/<user>/Desktop/dict.txt'' does not exist
ERROR: In:
ERROR:   [13] throw(error(existence_error(source_sink,'/<user>/Desktop/dict.txt'),_63876))
ERROR:    [9] toplevel_call(user:user: ...) at /home/u/tmp/swipl-devel/build.release/home/boot/toplevel.pl:1116
ERROR: 
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

absolute_file_name without access(read):


2 ?- absolute_file_name('/<user>/Desktop/dict.txt', X).
X = '/<user>/Desktop/dict.txt'.

No. without an option originally just produced the first expansion result. Long time ago this was changed to first try to find the first expansion result with access read and if that fails just produce the first expansion result.

Otherwise absolute_file_name/2,3 is designed to produce a path that actually works and attempts to return the same path regardless of how the file was searched for if it expands to the same file. This allows using the absolute path as an identifier you can compare. This is really hard though. We have case insensitive, case preserving, symbolic, hard links and (auto)mounting that all cause complications. For example, these paths are stored in saved states and .qlf files and after we reload these in a next session we want these paths to resolve to the file again.

Possibly realpath() would be a good alternative. It didn’t exist back than and I don’t know how portable it is. Linux docs say _XOPEN_SOURCE >= 500, which is encouraging.

1 Like