Vérifier si le système de fichiers est insensible à la casse en Python

y a-t-il un moyen simple de vérifier en Python si un système de fichiers est insensible à la casse? Je pense en particulier aux systèmes de fichiers comme HFS+ (OSX) et NTFS (Windows), où vous pouvez accéder au même fichier que foo, Foo ou FOO, même si le dossier est conservé.

15
demandé sur Lorin Hochstein 2011-10-24 03:29:50

6 réponses

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.
17
répondu Amber 2011-10-23 23:38:38

la réponse fournie par Amber laissera des débris de fichier temporaire à moins que la fermeture et la suppression soient traitées explicitement. Pour éviter cela, j'utilise:

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()))

bien que mes cas d'utilisation testent Généralement cela plus d'une fois, donc je planque le résultat pour éviter d'avoir à toucher le système de fichiers plus d'une fois.

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)

qui est légèrement plus lente si on ne l'appelle qu'une fois, et significativement plus rapide dans tous les autres cas.

5
répondu Steve Cohen 2016-04-12 18:10:38

à partir de la réponse D'Amber, j'ai trouvé ce code. Je ne suis pas sûr qu'il soit totalement robuste, mais il tente d'aborder certains problèmes dans l'original (que je vais mentionner ci-dessous).

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)))

sans spécifier le dir paramètre mkstemp, la question de la sensibilité des cas est vague. Vous testez la sensibilité des cas où se trouve le répertoire temporaire, mais vous voudrez peut-être connaître un chemin spécifique.

si vous convertissez le chemin complet mkstemp EN MAJUSCULES, vous pourriez rater une transition quelque part dans le chemin. Par exemple, j'ai un lecteur flash USB sur Linux monté en utilisant vfat à /media/FLASH. Test de l'existence de quoi que ce soit sous /MEDIA/FLASH échouera toujours parce que /media est sur une partition ext4 (sensible à la casse), mais la clé elle-même est insensible à la casse. Le partage de réseau monté pourrait être une autre situation comme celle-ci.

enfin, et peut - être qu'il va sans dire dans la réponse D'Amber, vous voudrez nettoyer le fichier temporaire créé par mkstemp.

2
répondu Eric Smith 2016-03-08 18:24:23

Bon point sur les différents systèmes de fichiers, etc. Eric Smith. Mais pourquoi ne pas utiliser le fichier temporaire.NamedTemporaryFile avec le paramètre dir et éviter de faire tout ce gestionnaire de contexte se soulever?

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()))

je dois également mentionner que votre solution ne garantit pas que vous êtes réellement tester la sensibilité de cas. Sauf si vous vérifiez le préfixe par défaut (en utilisant tempfile.gettempprefix ()) pour s'assurer qu'il contient un caractère minuscule. Donc inclure le préfixe ici n'est pas vraiment facultatif.

votre solution nettoie le fichier temp. Je suis d'accord qu'il semblait évident, mais on ne sait jamais, faire une?

2
répondu Steve Cohen 2016-04-14 02:07:01
import os

if os.path.normcase('A') == os.path.normcase('a'):
    # case insensitive
else:
    # case sensitive
0
répondu Liubov 2013-02-05 13:05:12

je pense que c'est la solution la plus simple à la question:

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

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

Si le système d'exploitation est insensible à la casse, puis les deux paramètres être normalisé à tous les cas inférieurs ou supérieurs avant la comparaison est effectuer.

0
répondu dRoneBrain 2018-03-28 21:53:24