Getting the absolute path from a PathBuf
Solution 1:
Rust 1.5.0 added std::fs::canonicalize
, which sounds pretty close to what you want:
Returns the canonical form of a path with all intermediate components normalized and symbolic links resolved.
Note that, unlike the accepted answer, this removes the ./
from the returned path.
A simple example from my machine:
use std::fs;
use std::path::PathBuf;
fn main() {
let srcdir = PathBuf::from("./src");
println!("{:?}", fs::canonicalize(&srcdir));
let solardir = PathBuf::from("./../solarized/.");
println!("{:?}", fs::canonicalize(&solardir));
}
Ok("/Users/alexwlchan/Developer/so-example/src")
Ok("/Users/alexwlchan/Developer/solarized")
Solution 2:
You can do this quite nicely using the path-clean crate and std::env::current_dir
. The benefit of this method over the other answers is that it resolves .
and ..
and it works even when the path doesn't exist.
use std::env;
use std::io;
use std::path::{PathBuf, Path};
use path_clean::PathClean;
pub fn absolute_path(path: impl AsRef<Path>) -> io::Result<PathBuf> {
let path = path.as_ref();
let absolute_path = if path.is_absolute() {
path.to_path_buf()
} else {
env::current_dir()?.join(path)
}.clean();
Ok(absolute_path)
}
Solution 3:
If I understand the PathBuf documentation correctly it does not treat "./"
as a special start to a path that says its relative.
You can however turn a relative path into an absolute one with std::env::current_dir
:
let relative_path = PathBuf::from("cargo_home");
let mut absolute_path = try!(std::env::current_dir());
absolute_path.push(relative_path)
This assumes that your relative path is relative to your current directory.
Solution 4:
There is https://crates.io/crates/path-absolutize now, for handling non-existent paths.