Проверьте, является ли файловая система нечувствительной к регистру в Python - PullRequest
15 голосов
/ 24 октября 2011

Есть ли простой способ проверить в Python, чувствительна ли регистр к файловой системе? Я имею в виду, в частности, файловые системы, такие как HFS + (OSX) и NTFS (Windows), где вы можете получить доступ к тому же файлу, что и foo, Foo или FOO, даже если регистр файлов сохранен.

Ответы [ 6 ]

17 голосов
/ 24 октября 2011
import os
import tempfile

# By default mkstemp() creates a file with
# a name that begins with 'tmp' (lowercase)
tmphandle, tmppath = tempfile.mkstemp()
if os.path.exists(tmppath.upper()):
    # Case insensitive.
else:
    # Case sensitive.
5 голосов
/ 12 апреля 2016

Ответ, предоставленный Amber, оставит временные файлы, если закрытие и удаление не обрабатываются явно. Чтобы избежать этого я использую:

import os
import tempfile

def is_fs_case_sensitive():
    #
    # Force case with the prefix
    #
    with tempfile.NamedTemporaryFile(prefix='TmP') as tmp_file:
        return(not os.path.exists(tmp_file.name.lower()))

Хотя мои сценарии использования обычно проверяют это более одного раза, поэтому я сохраняю результат, чтобы не касаться файловой системы более одного раза.

def is_fs_case_sensitive():
    if not hasattr(is_fs_case_sensitive, 'case_sensitive'):
        with tempfile.NamedTemporaryFile(prefix='TmP') as tmp_file:
            setattr(is_fs_case_sensitive,
                    'case_sensitive',
                    not os.path.exists(tmp_file.name.lower()))
    return(is_fs_case_sensitive.case_sensitive)

Что немного медленнее, если вызывается только один раз, и значительно быстрее во всех остальных случаях.

2 голосов
/ 14 апреля 2016

Хороший вопрос по различным файловым системам и т. Д. Эрик Смит. Но почему бы не использовать tempfile.NamedTeilitaryFile с параметром dir и избегать того, чтобы весь этот контекстный менеджер поднимал себя?

def is_fs_case_sensitive(path):
    #
    # Force case with the prefix
    #
    with tempfile.NamedTemporaryFile(prefix='TmP',dir=path) as tmp_file:
        return(not os.path.exists(tmp_file.name.lower()))

Я должен также упомянуть, что ваше решение не гарантирует, что вы действительно проверяете чувствительность к регистру. Если вы не проверите префикс по умолчанию (используя tempfile.gettempprefix ()), чтобы убедиться, что он содержит символ нижнего регистра. Таким образом, включение префикса здесь не является обязательным.

Ваше решение очищает временный файл. Я согласен, что это казалось очевидным, но никто не знает, один?

2 голосов
/ 08 марта 2016

Начиная с ответа Амбер, я придумал этот код. Я не уверен, что он полностью устойчив, но пытается решить некоторые проблемы в оригинале (о которых я упомяну ниже).

import os
import sys
import tempfile
import contextlib


def is_case_sensitive(path):
    with temp(path) as tmppath:
        head, tail = os.path.split(tmppath)
        testpath = os.path.join(head, tail.upper())
        return not os.path.exists(testpath)


@contextlib.contextmanager
def temp(path):
    tmphandle, tmppath = tempfile.mkstemp(dir=path)
    os.close(tmphandle)
    try:
        yield tmppath
    finally:
        os.unlink(tmppath)


if __name__ == '__main__':
    path = os.path.abspath(sys.argv[1])
    print(path)
    print('Case sensitive: ' + str(is_case_sensitive(path)))

Без указания параметра dir в mkstemp вопрос чувствительности к регистру неясен. Вы проверяете чувствительность к регистру, где бы ни находился временный каталог, но вы можете захотеть узнать о конкретном пути.

Если вы преобразуете полный путь, возвращаемый из mkstemp, в верхний регистр, вы можете пропустить переход где-нибудь в пути. Например, у меня есть флешка в Linux, смонтированная с использованием vfat на /media/FLASH. Проверка наличия чего-либо в /MEDIA/FLASH всегда будет неудачной, поскольку /media находится на (чувствительном к регистру) разделе ext4, но сама флешка не учитывает регистр. Установленные сетевые ресурсы могут быть другой ситуацией, подобной этой.

Наконец, и, возможно, само собой разумеется, в ответе Амбер вы захотите очистить временный файл, созданный mkstemp.

0 голосов
/ 29 марта 2018

Я считаю, что это самое простое решение вопроса:

from fnmatch import fnmatch
os_is_case_insensitive = fnmatch('A','a')

От: https://docs.python.org/3.4/library/fnmatch.html

Если в операционной системе не учитывается регистр, тогда оба параметрабудет нормализован для всех строчных и прописных букв перед выполнением сравнения.

0 голосов
/ 05 февраля 2013
import os

if os.path.normcase('A') == os.path.normcase('a'):
    # case insensitive
else:
    # case sensitive
...