Pathname conversion
lazarus / 61-Beginners
----------------------------------------------------------------------
Kaller · 2023-08-30 09:52
How do I convert a directory path like c:\more\of\this\ to match the
actual character case of windows file store?
----------------------------------------------------------------------
Zvoni · 2023-08-30 10:30
Quote from: Kaller on August 30, 2023, 11:52:49 amHow do I convert a
directory path like c:\more\of\this\ to match the actual character
case of windows file store?
Haven't understood a word.
Example?
----------------------------------------------------------------------
Kaller · 2023-08-30 10:41
the user enters a path like c:\my\work\
the system says path found: C:\My\Work
because the folders are named My and Work
----------------------------------------------------------------------
Zvoni · 2023-08-30 10:49
Quote from: Kaller on August 30, 2023, 12:41:06 pmthe user enters a
path like c:\my\work\
the system says path found: C:\My\Work
because the folders are named My and Work
Your point?
The Windows Filesystem is Case-Insensitive ("c:\my\work\" =
"C:\My\Work\")
so i don't know what you want to achieve.
What is the expected Result you want to get? "Path not found" or what?
----------------------------------------------------------------------
bonmario · 2023-08-30 10:52
Quote from: Kaller on August 30, 2023, 11:52:49 amHow do I convert a
directory path like c:\more\of\this\ to match the actual character
case of windows file store?
Try this:
https://www.freepascal.org/docs-
html/rtl/sysutils/expandfilenamecase.html
Hi, Mario
----------------------------------------------------------------------
Kaller · 2023-08-30 11:02
@BonMario: I tried without success. @Zvoni What if files get migrated
for example? I think knowing the actual case is a reasonable request.
----------------------------------------------------------------------
bonmario · 2023-08-30 11:26
I tried it now, and it works fine for me.
I use windows 11
----------------------------------------------------------------------
Kaller · 2023-08-30 11:35
I got it working. Have to specify fcmExact.
----------------------------------------------------------------------
bonmario · 2023-08-30 11:42
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
LeggiNomeFileRealeDaDisco(var NomeSrcReale: String); var NomeFileInp,
NomeFileOut:String; Posx:Integer; MatchFound:
TFilenameCaseMatch; begin //Inizializzazione variabili di lavoro
NomeFileInp:=NomeSrcReale; NomeFileOut:=''; while (NomeFileInp
<> '') do begin {$IFDEF MSWINDOWS} if (Length(NomeFileInp)
= 3) and (NomeFileInp[2] = ':') then begin
NomeFileOut:=UpperCase(ExtractFileDrive(NomeFileInp)) + NomeFileOut;
NomeFileInp:=''; end; {$ELSE} if
(NomeFileInp = PathDelim) then begin NomeFileOut:=PathDelim +
NomeFileOut; NomeFileInp:=''; end; {$ENDIF}
if (NomeFileInp <> '') then begin
NomeFileOut:=ExtractFileName(ExpandFileNameCase(NomeFileInp,
MatchFound)) + NomeFileOut; Posx:=Pos(PathDelim, NomeFileInp);
if (Posx > 0) then begin NomeFileOut:=PathDelim +
NomeFileOut; end else begin NomeFileInp:='';
end; NomeFileInp:=ExtractFileDir(NomeFileInp); end;
end; //Valorizzazione finale dell'output
NomeSrcReale:=NomeFileOut; end;
If i use this code:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var
NomeDir:String; NomeDir:='c:\users\bonmar\downloads';
LeggiNomeFileRealeDaDisco(NomeDir); ShowMessage(NomeDir);
the output is this:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
C:\Users\BONMAR\Downloads
Hi, Mario
----------------------------------------------------------------------
Kaller · 2023-08-30 12:03
Nice. Thanks.
----------------------------------------------------------------------
KodeZwerg · 2023-08-30 12:06
My try, should be crosscompile compatible:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i function
SensitivePath(const APath: string): string; function GetCurrent(const
APath: string): string; var searchRec: TSearchRec; begin
Result := ''; if FindFirst(ExcludeTrailingBackslash(APath),
faAnyFile, searchRec) = 0 then begin Result :=
searchRec.Name; FindClose(searchRec); end; end;var s:
string; i: Integer; arr: TStringArray;begin if ((not
FileExists(APath)) and (not DirectoryExists(APath))) then
Exit(APath); s := ''; Result := ''; arr :=
APath.Split([PathDelim]); for i := Low(arr) to High(arr) do begin
s := s + arr[i] + PathDelim; if i > 0 then arr[i] :=
GetCurrent(s); Result := Result + arr[i] + PathDelim; end;
Result := ExcludeTrailingBackslash(Result);end;Only tested with path,
not filenames.
//edit:
Works for both same good, files, folder.
My test:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
WriteLn(SensitivePath('c:\windows\SysteM32'));
WriteLn(SensitivePath('c:\WindOws\SyStem32\'));
WriteLn(SensitivePath('c:\WinDows\SystEm32\D3D12CorE.Dll'));The
Result:
Quotec:\Windows\System32
c:\Windows\System32\
c:\Windows\System32\D3D12Core.dll
----------------------------------------------------------------------
Bart · 2023-08-30 19:07
function FindDiskFileName in FileUtils might be what you are looking
for.
Bart
----------------------------------------------------------------------
Kaller · 2023-08-30 20:38
On further investigation I think I understand the issues I was having.
It appears that standard filename functions are not the answer, they
do things like only work with the last item in the path. So even
something like a trailing path delimiter will throw them off. The
routines provided by helpful posters here will be great. Is it
possible to get a directory without having to physically enter it?
I got GPT to convert Mario's code to English and compress it.
----------------------------------------------------------------------
KodeZwerg · 2023-08-30 22:13
Quote from: Kaller on August 30, 2023, 10:38:24 pmIs it possible to
get a directory without having to physically enter it?No.
If you want to have it like it is on disk than you must access disk,
sound logical or?
Everything else is just to beautify a string but not to get it like
you wanted to have.
Quote from: Kaller on August 30, 2023, 10:38:24 pmI got GPT to convert
Mario's code to English and compress it.Uhm... applause?
----------------------------------------------------------------------
Kays · 2023-08-30 22:16
Quote from: Zvoni on August 30, 2023, 12:49:39 pm[…] The Windows
Filesystem“The Windows Filesystem”? Jesus Christ.
Quote from: Zvoni on August 30, 2023, 12:49:39 pmCase-Insensitive
[…]Meanwhile NTFS does support case-sensitive filenames. You will need
to traverse the entire path checking each directory whether it has
case-sensitive filename support enabled.
Quote from: Kaller on August 30, 2023, 12:41:06 pmthe user enters a
path like c:\my\work\
the system says path found: C:\My\WorkI bet the WinAPI (or other
essential library) provides some sort of canonicalize pathname
function. Evidently you lack understanding of NTFS, so I strongly
advise against implementing a mechanism by yourself.
----------------------------------------------------------------------
Kaller · 2023-08-31 00:33
Case sensitivity is a processing distinction, not a fact about files.
Files themselves do have case structure and it can be significant when
migrating files between systems. Mario's answer is nice because it
doesn't involve the app changing the current directory just to
determine the actual case on disk. I reproduce below the English
version courtesy of GPT. It doesn't require changing the current
folder.
----------------------------------------------------------------------
Bogen85 · 2023-08-31 02:05
Quote from: Kaller on August 31, 2023, 02:33:27 amCase sensitivity is
a processing distinction, not a fact about files. Files themselves do
have case structure and it can be significant when migrating files
between systems. Mario's answer is nice because it doesn't involve
the app changing the current directory just to determine the actual
case on disk. I reproduce here the English version courtesy of GPT.
It doesn't require changing the current folder.
...
Could you please put code between the
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i // code
here
[code=pascal]
// code here
[/code]
code tags on this forum? (regular ASCII brackets, not Unicode
brackets) (see the [#]button in the formatting toolbar)
As far as GPT goes, well, best to make sure it works and not
necessarily advertise the fact, use and promotion of GPT on these
forums often results in reactions you might find either annoying or
unpleasant, and everything in between...
----------------------------------------------------------------------
Kaller · 2023-08-31 02:44
The code is Mario's I just translated it and gave it some minor
tweaks. Yes I tested it before hand and appears to work very well.
I wasn't sure how to mark it up so now I know
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
GetDiskFileName(var RealSourceName: String);var InputFileName,
OutputFileName: String; MatchFound: TFilenameCaseMatch;begin
InputFileName := RealSourceName; OutputFileName := ''; while
InputFileName <> '' do begin {$IFDEF MSWINDOWS} if
(Length(InputFileName) = 3) and (InputFileName[2] = ':') then
begin OutputFileName :=
UpperCase(ExtractFileDrive(InputFileName)) + OutputFileName;
InputFileName := ''; end; {$ELSE} if InputFileName =
PathDelim then begin OutputFileName := PathDelim +
OutputFileName; InputFileName := ''; end; {$ENDIF}
if InputFileName <> '' then begin OutputFileName :=
ExtractFileName(ExpandFileNameCase(InputFileName, MatchFound)) +
OutputFileName; if Pos(PathDelim, InputFileName) > 0 then
OutputFileName := PathDelim + OutputFileName else
InputFileName := ''; InputFileName :=
ExtractFileDir(InputFileName); end; end; RealSourceName :=
OutputFileName;end;
----------------------------------------------------------------------
Zvoni · 2023-08-31 06:46
Quote from: Kays on August 31, 2023, 12:16:02 amQuote from: Zvoni on
August 30, 2023, 12:49:39 pm[…] The Windows Filesystem“The Windows
Filesystem”? Jesus Christ.
Right. You got me there
Quote from: Kays on August 31, 2023, 12:16:02 amQuote from: Zvoni on
August 30, 2023, 12:49:39 pmCase-Insensitive […]Meanwhile NTFS does
support case-sensitive filenames. You will need to traverse the entire
path checking each directory whether it has case-sensitive filename
support enabled.
Since when????
You mean to tell me, that on NTFS (if activated) "c:\TEMP" <>
"c:\temp"?
----------------------------------------------------------------------
Thaddy · 2023-08-31 08:32
Quote from: Zvoni on August 31, 2023, 08:46:49 amSince when????
You mean to tell me, that on NTFS (if activated) "c:\TEMP" <>
"c:\temp"?
Quote:
"The NTFS file system is case-sensitive. This means that files with
the same name but different case are treated as distinct files.
However, the Windows API presents an abstraction of NTFS that makes it
appear as a case-preserving file system. This means that the API
remembers the filename case, but it does not distinguish between files
whose names only differ in case.
If you want to enable case sensitivity for a folder in NTFS, you can
use the fsutil.exe tool to set the folder’s content as case-
sensitive."
So yes, the NTFS file system itself is case sensitive, but the Windows
API abstracts that away. And can be mitigates by fsutil.
This dates back from the days that Windows pro versions were POSIX
compliant by default, so since the introduction of NTFS. NTFS on Linux
file names are always treated as case sensitive.
The command is: fsutil file setcasesensitiveinfo