Search code examples
javaglob

How to search (case-sensitive) for files using Java glob pattern?


I am checking the getPathMatcher method of FileSystem class. The documentation of the method says:

For both the glob and regex syntaxes, the matching details, such as whether the matching is case sensitive, are implementation-dependent and therefore not specified.

I tested this and came to know that by default it is case-insensitive. How to make it case-sensitive?

I am using JDK7u25 on Windows7.


Solution

  • No, it is not case-insensitive by default. As the doc says, case sensitivity is implementation dependent.

    And NTFS is case preserving but case insensitive. That is, a file named README.txt will keep its case (case preserving); but trying and finding it by the name Readme.TXT, say, will work (case insensitive).

    This is not the case on Unix systems, whose filesystems are case sensitive.

    Unfortunately, there is no way around that! Other than creating your own Filesystem implementation wrapping the default and make it case sensitive.

    Here is an example of a VERY limited purpose FileSystem which will be able to generate a "case sensitive matching" of filename extensions:

    public final class CaseSensitiveNTFSFileSystem
        extends FileSystem
    {
        private static final Pattern MYSYNTAX = Pattern.compile("glob:\\*(\\..*)");
    
        private final FileSystem fs;
    
        // "fs" is the "genuine" FileSystem provided by the JVM
        public CaseSensitiveNTFSFileSystem(final FileSystem fs)
        {
            this.fs = fs;
        }
    
        @Override
        public PathMatcher getPathMatcher(final String syntaxAndPattern)
        {
            final Matcher matcher = MYSYNTAX.matcher(syntaxAndPattern);
            if (!matcher.matches())
                throw new UnsupportedOperationException();
            final String suffix = matcher.group(1);
            final PathMatcher orig = fs.getPathMatcher(syntaxAndPattern);
    
            return new PathMatcher()
            {
                @Override
                public boolean matches(final Path path)
                {
                    return orig.matches(path)
                        && path.getFileName().endsWith(suffix);
                }
            };
        }
    
        // Delegate all other methods of FileSystem to "fs"
    }