Problem rozwiązany, ale niezbyt ładnie...
Jestem nekromantą i reanimuję stary serwis napisany w PHP.
Miał on jakiś CMS, który bazę danych prowadził w plikach tekstowych - co akurat mało przeszkadza, bo mogę sobie łatwo wszystkie newsy przetworzyć na markdown (Jekyll - GitHub Pages) moim skryptem.
Newsy miały do siebie przypisane zdjęcia i o dziwo niektóre wpisy w bazie miały nazwy plików zapisane inną wielkością znaków, niż pliki na serwerze. Np. zamiast *.jpg
, było *.JPG
.
Więc po przejechaniu moim skryptem na wygenerowanych stronach niektóre zdjęcia się nie ładowały.
Więc musiałem dodać weryfikację ścieżki pliku. Tak, żeby wielkość znaków ścieżki zdjęcia wpisanej na stronie, była zgodna z wielkością znaków zapisanego pliku.
Pythonowe funkcje operują na stringach, bez rozeznania w systemie plików.
Chat GPT na począku proponował takie rozwiązanie:
if os.path.exists(path):
return os.path.normpath(path)
Po moim komentarzu:
normpath just converts string argument. It doesn't look up the file in filesystem. I want a solution that reads file's case sensitive name.
Wymyślił coś takiego:
import os
import ctypes
from ctypes import wintypes
def get_case_sensitive_path(path):
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
FILE_SHARE_READ = 1
OPEN_EXISTING = 3
FILE_ATTRIBUTE_NORMAL = 0x80
lpFileName = os.path.abspath(path)
dwDesiredAccess = 0
dwShareMode = FILE_SHARE_READ
dwCreationDisposition = OPEN_EXISTING
dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT
hTemplateFile = None
hFile = kernel32.CreateFileW(
lpFileName,
dwDesiredAccess,
dwShareMode,
None,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
)
try:
result = ctypes.create_unicode_buffer(512)
kernel32.GetFinalPathNameByHandleW(hFile, result, ctypes.sizeof(result), 0)
return result.value
finally:
kernel32.CloseHandle(hFile)
To działa i na tym poprzestałem.
W czystym Pythonie pewnie mógłbym listować katalog nadrzędny i szukać nazwy pliku, żeby otrzymać nazwę, która jest case sensitive.
A może ktoś ma inną propozycję?