Careful with chdir/1

Windows 10 seems to keep a working directory per drive letter.
And node.js chdir seems to respect that. Now I get on SWI-Prolog:

?- pwd.
% c:/users/foobar/documents/prolog/
true.
?- chdir('d:').
true.
?- chdir('c:').
true.
?- pwd.
% c:/
true.

Whereas when I use node.js, I get:

?- pwd.
% C:\Users\foobar
true.
?- chdir('D:').
true.
?- chdir('C:').
true.
?- pwd.
% C:\Users\foobar
true.

Possible to change the active drive letter without affecting the
working directory in SWI-Prolog?

Surely it is possible. It is not clear whether it is desirable though as it breaks compatibility with Unix-like systems. I think we can better wait until Microsoft sees the light and implements sensible file system semantics. They seem to be moving slowly in that direction (as well as towards UTF-8 which would allow us finally to exchange text files transparently when they contain non-ASCI characters).

2 Likes

Unix files systems don’t have file or directory paths of this type,
thats Windows specific, and counts as an absolute path on Windows,
or a relative indexed path, indexed by drive letter:

<drive>:<path>

So basically you should be able to distinguish chdir('c:') from
chdir('c:/'), like node.exe can do:

Only change the active drive:

?- pwd.
% D:\
true.
?- chdir('c:').
true.
?- pwd.
% C:\Users\rburs
true.

Change the active drive and the working directory of this drive:

?- pwd.
% D:\
true.
?- chdir('c:/').
true.
?- pwd.
% c:\
true.

Its consistent with that an empty path is a relative path, so its actually
a two step process. Change the active drive, and then update the working
directory. But updating via empty path in the case C: results in the same

working directory as before. On the other hand in the case C:/ the
path is not empty, it is /, so that one gets indeed a working directory
update of the drive C:. But I just see node.exe might have a glitch,

or maybe this is indented? It doesn’t normalize the drive letter to
upper case as seen in the second example above.

As a consequence, being at c: the code below would no longer work, ending up in c:/work rather than c:. Note that chdir/1 is just a commandline shortcut to working_directory/2.

     setup_call_cleanup(
         working_directory(Old, 'c:/work'),
         do something,
         working_directory(_, Old)).

It is advised to change the working directory at most once during program initialization and do not touch is afterwards because the working directory is shared between the threads. Some systems nowadays implement a thread-specific working directory, but not all AFAIK :frowning:

.

Yes, could be a problem if you omit path slashification. But if you
slashify Windows paths, you do not get any problem.

Works on my side, you cannot be at c:, i.e. letter without
slashified path, you can only be at c:/:

?- working_directory(_, 'c:\\'), 
       working_directory(NOW, NOW).
NOW = 'c:/'.

?- working_directory(OLD, 'c:\\users'), working_directory(_, OLD), 
        working_directory(NOW, NOW).
OLD = NOW, NOW = 'c:/'.

Edit 25.05.2022:
The usual Windows command terminal does also slashify, but
it does not slashify with / rather with \.

I see. That would make c: distinct from c:/ and the working directory returning the root of a drive as x:/, so you can go back there. I doubt I like that. I’d rather have a win_* predicate to change the current drive. I don’t see much value in it though. What would you want to use it for?

Maybe the best advice is, even if it happens that yoru chdir() supports it,
don’t make use of it in some Prolog scripts, since it is not portable.