Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you force os.path.isfile() to use case insensitivity when checking a file on a case-sensitive file system?

If I use os.path.isfile("foo.txt") to check a file named Foo.txt, the function returns True on case-insensitive file systems and Windows. However, it returns False on case-sensitive file systems. Is there a way to force case-insensitive checking for isfile() even on case-sensitive file systems? I know there is a way to force case-sensitivity for this function on Windows, but what about the other way around?

Background

I'm working with DITA content. If you develop DITA content on Windows and deploy your content to a case-sensitive Linux server, you can end up with broken links between topics if your href attributes have characters with a different case than the actual target files. I'm trying to make a script that goes through every href attribute in our DITA source that is not an external link, and updates it to match the case of the actual file. I'm able to obtain the href attribute with the beautifulsoup module, but I'm having a hard time figuring out how to check and verify the actual file name so I can use that string to update the href attribute in my DITA source.

A more heavy-handed approach would be to just go through and convert every href and its target file to lower case, but that can cause different problems if external sites have links to your content and they already have the correct case working.

It's possible that the isfile() function isn't the right tool for this job, but it's a start. I guess I could always just run this script on Windows, but that's not very elegant. It would be best to have the script run properly on most systems.

like image 453
dwightjl Avatar asked Nov 22 '22 12:11

dwightjl


1 Answers

You can list all the files in the parent directory and check the filenames case-insensitively:

import os

def getfile_insensitive(path):
    directory, filename = os.path.split(path)
    directory, filename = (directory or '.'), filename.lower()
    for f in os.listdir(directory):
        newpath = os.path.join(directory, f)
        if os.path.isfile(newpath) and f.lower() == filename:
            return newpath

def isfile_insensitive(path):
    return getfile_insensitive(path) is not None

The function isfile_insensitive returns a boolean that specifies if there is a filename in the parent directory that matches the one you are looking for case-insensitively.

The function getfile_insensitive returns the path to the existing filename (with correct case), so you can use that filename safely in your system.

like image 183
enrico.bacis Avatar answered Nov 25 '22 02:11

enrico.bacis