Ownership for path in walkdir

Hi

I'm new to rust. I'm trying to loop thru all files in /tmp-directory. Then add them to a Vec.
But I got problem with ownership for path. I'm using a crate for walking directory's: https://crates.io/crates/walkdir.

Here is my code:

use walkdir::WalkDir;

fn main() {
    // Store path.
    let mut paths = Vec::new();

    // Walkdir.
    for entry in WalkDir::new("/tmp") {
        let entry = entry.unwrap();
        let path = entry.path().display();

        paths.push(path);
    }
}

Here is the error message:

error[E0597]: `entry` does not live long enough
  --> src/main.rs:10:20
   |
10 |         let path = entry.path().display();
   |                    ^^^^^ borrowed value does not live long enough
11 | 
12 |         paths.push(path);
   |         ----- borrow later used here
13 |     }
   |     - `entry` dropped here while still borrowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0597`.
error: Could not compile `walkfiles`.

I have tried to use entry as a reference then getting the path.
Any ideas?

// Micke

1 Like

My guess: You're trying to push a reference derived from a value that only exists during the for loop. When you push entry, instead do:

paths.push(path.clone());

Edit: I said originally that the value paths dies on each iteration, I believe that to be wrong, it lives as long as the for loop. Edited to reflect.

This will make a copy and give your own to play with.

1 Like

I am a new user myself, but I can confirm the issue.

If you look at the display() method, it returns a Display { path: self } which means that the Display object that is being pushed onto the vector also holds the entry that is created from the let entry = entry.unwrap().

That entry variable is then dropped after the end of the function, even though the vector wants to hold onto it because its inside the Display that has been pushed into it.

Also, Display does not implement clone(), so you can't clone it without implementing that trait.

Not sure on a solution yet. Learning with you.

Hm... Will path.to_string() work? Since it implements Display?

1 Like

If you want a String representation of each path---which cannot represent all possible paths---then you can use entry.path().display().to_string(), or, more explicitly, entry.path().to_string_lossy(). (The latter should always be preferred over the former, since it makes it clear that a lossy conversion is happening.)

With that said, the "correct" solution should not be to collect a Vec<String>, but rather, to collect a Vec<PathBuf>, which you can do via entry.path().to_path_buf(). This will preserve all possible paths, where as using Vec<String> will only preserve paths that are valid UTF-8.

4 Likes

Hi

Thanks for all the answers. I manage to figure out how to store the path in the Vec, as you mention I need to convert it to a String.

But I have now also learn its better to store it as a path_buf. Thanks!

// Micke

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.