Minimizing a file path I have a simple program that "minimizes" a file path. Minimizing simply means replacing unnecessary file entries with entries that mean the same thing:


path1/path2/../path3 is replaced with path1/path3
path1/./path2 is replaced with path1/path2


I've achieved this using regex and it seems to cover all cases, but it also feels very slow and I have a hunch it might be prone to infinite loops:

private static final Pattern ONE_DOT = Pattern.compile("/\\./");
private static final Pattern TWO_DOTS = Pattern.compile("[^/]+/\\.\\./?");

public static String minimize(final String in) {
    String tmp = in;
    while (!stringIsMinimized(tmp)) {
        tmp = ONE_DOT.matcher(tmp).replaceAll("/");
        tmp = TWO_DOTS.matcher(tmp).replaceAll("");
    }
    return tmp;
}

public static boolean stringIsMinimized(final String str) {
    return !(ONE_DOT.matcher(str).find() || TWO_DOTS.matcher(str).find());
}
Your code actually doesn't work, because you use replaceAll. This means that your pattern will allow you to match ../../ and replace it with , resulting in a lost double-back. You can fix this two ways:


You could change the replaceAll to replaceFirst
You could change the pattern to exclude ../../ ([^/.]+/\\.\\./? works)


You can then simplify your loop since the ONE_DOT case will be matched properly so you don't need to split out a check for minimization.

Thus I would suggest:

private static final Pattern ONE_DOT = Pattern.compile("/\\./");
private static final Pattern TWO_DOTS = Pattern.compile("([^/.]+/\\.\\.)+/?");

public static String minimize(final String in) {
    String tmp = in;

    tmp = ONE_DOT.matcher(tmp).replaceAll("/");

    while (TWO_DOTS.matcher(tmp).matches())
        tmp = TWO_DOTS.matcher(tmp).replaceAll("");

    return tmp;
}


At least as a first-pass improvement. There may be a way to do it without the loop using some kind of counting regular expression, but off the top of my head I'm not sure.