Kat
Kat

Reputation: 4695

Java two dots at the end of a path have unexpected results

I've run into what I thought was unusual behavior when working with some File objects.

import java.io.File;

public class MyClass
{
    public static void main(String[] args)
    {
        File file = new File("C:\\x..");

        System.out.println(file.isDirectory());

        System.out.println(file.listFiles());
    }
}

Assuming that some directory C:\x exists, file.isDirectory() will return true with the added two dots at the end of the path. This replicates the behavior in the command line, where cd x.. will change the directory to x.

However, when calling file.listFiles(), the method returns null, which is only supposed to happen if the file is not a directory. This seems to be inconsistent with the definition of the listFiles().

Why is this so? And why does having two dots at the end of the path go to the same directory as if there was no dots?

This problem seems to be exclusive to Windows. Linux correctly (?) returns false for isDirectory().

Upvotes: 3

Views: 1968

Answers (2)

Jason C
Jason C

Reputation: 40356

Windows trims trailing dots from path and filenames. I am unable to find a concrete reference for this, it's just one of those mysterious things that has always been that way.

It trims the trailing dots from the full pathname, not the individual components.

Therefore, while "C:\x...." is the same as "C:\x", "C:\x....\filename" is not the same as "C:\x\filename", as the latter does not have trailing dots.

You would have to look at the JDK's native FileSystem source on Windows to see precisely how it is obtaining a list of files, but I suspect it's doing some kind of search on e.g. "C:\x..\*.*" using Windows' FindFirstFile API call or something, where the dots are no longer trailing. In other words, presuming "C:\x" is a directory, while the path "C:\x.." is a directory, "C:\x..\*.*" matches nothing, and "C:\x..\subdirectory" does not map to "C:\x\subdirectory".

You should avoid using such paths. I'm not sure how you obtained that path string in the first place.

You can use File.getCanonicalPath() or File.getCanonicalFile() to convert it back to a more useable pathname.

By the way, if you want to have some fun with Windows, type the following in a command prompt (assuming "c:\windows\temp" exists, otherwise replace with some other path):

echo > \\?\c:\windows\temp\x.

The \\?\ prefix in Windows disables filename processing and expansion. Now delete the resulting file. Try it in Explorer too.

Spoiler:

You'll have to delete it with a wildcard from the console, e.g. del x?

Upvotes: 4

Antoniossss
Antoniossss

Reputation: 32527

You forgot to add extra slashes before .. to it should be c:\\x\\... This will point you to C: indeed

Upvotes: -1

Related Questions