public final Iterator<Path> dirsIterator() {
		return new Iterator<Path>() {
			private DirTree currentTree = walkTo(DirTree.this.base);
			private Iterator<String> iter = this.currentTree.directories
					.keySet().iterator();
			private final ArrayDeque<Iterator<String>> iterStack = new ArrayDeque<>();

			@Override
			public boolean hasNext() {
				while (true) {
					if (this.iter.hasNext()) {
						return true;
					}
					if (this.iterStack.isEmpty()) {
						return false;
					}
					// pop
					this.currentTree = this.currentTree.parent;
					this.iter = this.iterStack.removeLast();
				}
			}

			@Override
			public Path next() {
				final String next = this.iter.next();
				final Path ret = this.currentTree.buildPath().resolve(next);
				if (this.currentTree.directories.get(next) != null) {
					this.iterStack.add(this.iter);
					this.currentTree = this.currentTree.directories.get(next);
					this.iter = this.currentTree.directories.keySet()
							.iterator();
				}
				return ret;
			}

			@Override
			public void remove() {
				throw new UnsupportedOperationException();
			}

		};
	}