Nth ancestor of a Path

I often find myself needing to find a folder 2-3-4 levels above a given file in the filesystem. Rust provides the parent method which is the immediate parent and the ancestors that iterates over al the parts in the directory path. I would like something that would be path.parent(3) that would be something like

I implemented it in two ways. I'd be glad to get your feedback on the implementation, and if you think this addition to the std::path::Path sounds like a good idea then how should I go about proposing it?

use std::path::Path;

fn main() {
    let path = Path::new("one/two/three/four/five/six.rs");

    //match ancestor(&path, 0) {
    //    Some(val) => println!("ancestor: '{}'", val.display()),
    //    None => println!("No such ancestor"),
    assert_eq!(ancestor(&path, 0), Some(Path::new("one/two/three/four/five/six.rs")));
    assert_eq!(ancestor(&path, 1), Some(Path::new("one/two/three/four/five")));
    assert_eq!(ancestor(&path, 5), Some(Path::new("one")));
    assert_eq!(ancestor(&path, 6), Some(Path::new("")));
    assert_eq!(ancestor(&path, 7), None);

    assert_eq!(parentn(&path, 0), Some(Path::new("one/two/three/four/five/six.rs")));
    assert_eq!(parentn(&path, 1), Some(Path::new("one/two/three/four/five")));
    assert_eq!(parentn(&path, 5), Some(Path::new("one")));
    assert_eq!(parentn(&path, 6), Some(Path::new("")));
    assert_eq!(parentn(&path, 7), None);

fn ancestor(mut path: &Path, mut n: u16) -> Option<&Path> {
    while n > 0 {
        match path.parent() {
            Some(value) => path = value,
            None => return None,
        n = n - 1;
    return Some(path);

// recursive
fn parentn(path: &Path, n: u16) -> Option<&Path> {
    if n == 0 {
        return Some(path);
    match path.parent() {
        Some(value) => parentn(value, n-1),
        None => None,

You can use the question mark operator to simplify this:

fn ancestor(mut path: &Path, n: u16) -> Option<&Path> {
    for _ in 0..n {
        path = path.parent()?;

Nice. Thank you.

there is Path::ancestors.

So I would use path.ancestors().nth(n).


Oh, I knew ancestors, but I was not aware the nth() thing. Very nice.

nth is available on all iterators, just to be clear.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.