Returns the lexically cleaned form of the path name, <i>usually</i> (but not always) equivalent to the original. The following heuristics are used: <ul> <li>empty string becomes . <li>. stays as . <li>fold out ./ <li>fold out ../ when possible <li>collapse multiple slashes <li>delete tr
(String pathname)
| 731 | * @since 11.0 |
| 732 | */ |
| 733 | public static String simplifyPath(String pathname) { |
| 734 | checkNotNull(pathname); |
| 735 | if (pathname.isEmpty()) { |
| 736 | return "."; |
| 737 | } |
| 738 | |
| 739 | // split the path apart |
| 740 | Iterable<String> components = Splitter.on('/').omitEmptyStrings().split(pathname); |
| 741 | List<String> path = new ArrayList<>(); |
| 742 | |
| 743 | // resolve ., .., and // |
| 744 | for (String component : components) { |
| 745 | switch (component) { |
| 746 | case ".": |
| 747 | continue; |
| 748 | case "..": |
| 749 | if (path.size() > 0 && !path.get(path.size() - 1).equals("..")) { |
| 750 | path.remove(path.size() - 1); |
| 751 | } else { |
| 752 | path.add(".."); |
| 753 | } |
| 754 | break; |
| 755 | default: |
| 756 | path.add(component); |
| 757 | break; |
| 758 | } |
| 759 | } |
| 760 | |
| 761 | // put it back together |
| 762 | String result = Joiner.on('/').join(path); |
| 763 | if (pathname.charAt(0) == '/') { |
| 764 | result = "/" + result; |
| 765 | } |
| 766 | |
| 767 | while (result.startsWith("/../")) { |
| 768 | result = result.substring(3); |
| 769 | } |
| 770 | if (result.equals("/..")) { |
| 771 | result = "/"; |
| 772 | } else if (result.isEmpty()) { |
| 773 | result = "."; |
| 774 | } |
| 775 | |
| 776 | return result; |
| 777 | } |
| 778 | |
| 779 | /** |
| 780 | * Returns the <a href="http://en.wikipedia.org/wiki/Filename_extension">file extension</a> for |