String (@NotNull VirtualFile file) { var parent = file.getParent(); if (parent == null || parent.isCaseSensitive()) { return super.getCanonicallyCasedName(file); } String originalFileName = file.getName(); long t = LOG.isTraceEnabled() ? System.nanoTime() : 0; try { File ioFile = convertToIOFile(file); File canonicalFile = ioFile.getCanonicalFile(); String canonicalFileName = canonicalFile.getName(); if (!SystemInfo.isUnix) { return canonicalFileName; } // linux & mac support symbolic links // unfortunately canonical file resolves symlinks // so its name may differ from name of origin file // // Here FS is case-sensitive, so let's check that original and // canonical file names are equal if we ignore name case if (canonicalFileName.compareToIgnoreCase(originalFileName) == 0) { // p.s. this should cover most cases related to not symbolic links return canonicalFileName; } // Ok, names are not equal. Let's try to find corresponding file name // among original file parent directory File parentFile = ioFile.getParentFile(); if (parentFile != null) { // I hope ls works fast on Unix String[] canonicalFileNames = parentFile.list(); if (canonicalFileNames != null) { for (String name : canonicalFileNames) { // if names are equals if (name.compareToIgnoreCase(originalFileName) == 0) { return name; } } } } // No luck. So ein mist! // Ok, garbage in, garbage out. We may return original or canonical name // no difference. Let's return canonical name just to preserve previous // behaviour of this code. return canonicalFileName; } catch (IOException | InvalidPathException e) { return originalFileName; } finally { if (t != 0) { t = (System.nanoTime() - t) / 1000; LOG.trace("getCanonicallyCasedName(" + file + "): " + t + " mks"); } } }