Search code examples
pythonwindowsshellos.path

Python os.path.isdir returns true for dots


I'm programming my own shell in python. Right now I'm trying to implement the cd command to my shell.

The function that performs this command has several variables:

self.current_dir = "C:\\" - The default value, it changes depends on the user's input using the cd command

dir = "..." - The requested directory that the user types. "..." is an example for an input that causes the problem.

Here is my code:

def command_cd(self, dir):
    if os.path.isdir(self.shell.current_dir + dir):
        self.shell.current_dir = self.shell.current_dir + dir + "\\"

The problem is that for some strange reason, os.path.isdir(self.shell.current_dir + dir) returns True when the user types dots (Just like the example inputs for the variables which I gave above).

The problem occurs even if you change the amount of dots (even above 5 dots) and I really have no idea what causes it.

There's obviously no folder named ... or anything like it.

If my problem isn't clear enough please comment and I'll edit it


Solution

  • . is the current directory, .. is the parent directory, and there no such reference of anything greater than two dots.

    But however, the reason for why os.path.isdir() returns True is because python registers everything greater than two dots as one dot.

    import os
    
    print(os.path.abspath(".......") == os.path.abspath("."))
    print(os.path.abspath("....") == os.path.abspath("."))
    
    # and that
    print(os.path.samefile('......', '.'))
    # also prints True
    

    They will all print True, since ....,....... and . points to the same place.


    As chepner has pointed out in the comments, this problem doesn’t occur in POSIX systems, whereas it’s caused by os.stat mistakenly equates '....' with '.' (which is not the case, see later edit)


    Important Edit:

    Commented by eriksun:

    Windows os.path.isdir is implemented by calling GetFileAttributes, which calls NtQueryAttributesFile. Like all file system functions, first it has to convert the DOS path to a native NT path. To the kernel "." and ".." are just normal names, so the runtime library first has to normalize the path via the function RtlGetFullPathName_Ustr, which also gets used by os.path.abspath, so the result is similar. The way it reduces more than two dots and trailing spaces in the final component is a legacy inherited from DOS. It's doing its best to emulate an OS from the 1980s.

    Therefore this problem has nothing to do with python itself, as this problem occurs in Windows cmd as well, cd c:\..... or cd .\....\.. Windows will still let you get away with it, by referencing two than two dots with one dot. As it was inherited from DOS to reduce more than two dots to one and remove trailing spaces.