Add "Cli style" relative path to a pathbuf

I'm doing a cli app using clap that require a path as an input. Except, this path can be both absolute and relative.

Having an absolute path is fine, and having an "extending" relative path (ex: "images/cats") is easy to deal with, but I cannot find anything to deal with paths that go to the parent directory (ex: "../images/cats").

Is there any sneaky method I can use? Or crate?

It's not clear to me what you actually want. Do you want to canonicalize your paths to make them absolute? Do you just want to expand .s and ..s? Those are actual real paths, at least in Unix filesystems, which is why ls -a lists them out, so you may not even have to do anything at all.

1 Like

I want to make them absolute.
So something like "/home/user" + "../user2" turns into "/home/user2", like ls does

This is an unix example, but I also need an equivalent for windows.

1 Like

This transformation is not valid in general, e.g.

$mkdir -p a/b/c

$touch a/b/c/d

$mkdir c

$touch c/e

$ln -s a/b/c f

$ls f/../c
.  ..  d

$ls c
.  ..  e

... as you can see, f/../c and c are different directories.

Yes. that's the reason why realpath involves actually walking the file system tree.

std::path::absolute as the module suggests, operates only on the path so will succeed even if the file does not exist. On the other hand, due to the symlink issues above, it will not collapse ".." components.

You could manually iterate on path.components() to manually build the resolved path using push and pop ignoring symlinks, but it's non-standard behavior that could surprise your users.

1 Like

Neat, though there's enough weird footguns that it should probably end up with a very long documentation block if/when it lands! Rust generally tries to surface such weirdness where it can unlike the prior art.

1 Like

Yeah, I agree that it's both sometimes useful but also foot-gunny when used against actual filesystem paths.