Help. multiples iterates in folder

Hi. i am fool.
i try iterate recursive in folders:
I need understand, I don't know whether to use String or Path? or know its methods.

folder contain -> folder1 and folder2.

use std::path::Path;
fn main() {
    let root = Path::new("/home/pichibw/folder/");    
    // iterate over root
    for a in fs::read_dir(&root).unwrap() {        
        println!("{}", a.unwrap().path().display());
         for b in fs::read_dir(&.unwrap().path().display()).unwrap() {
             println!("{}", b.unwrap().path().display());
         } // end for b
    } //end for a

for b in fs::read_dir(&a.unwrap().path().display()).unwrap() {
the trait AsRef<Path> is not implemented for std::pat h::Display<'_>
required by a bound introduced by this call

Follow the types and documentation.

pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<ReadDir>

ReadDir says:

This iterator is returned from the read_dir function of this module and will yield instances of io::Result<DirEntry>. Through a DirEntry information like the entry’s path and possibly other metadata can be learned.

And from there we can see that path returns a PathBuf.

PathBuf implements AsRef<Path> so you should keep that around for your second read_dir. The Display<'_> returned by Path::display is just for printing, because operating system paths aren't necessarily valid UTF8 or any other encoding.

There is one more wrinkle that I can't blame anyone for tripping over. The libs team made the questionable decision of returning various io::ErrorKind errors without stabilizing them. As such there is no proper way on stable to be sure your read_dir failed due to calling it on something that's not a directory. Instead, you're going to have to do a racy check either before attempting the read_dir or after attempting it and getting an error.

You can use DirEntry::file_type to get a FileType for testing.

Here's what it looks like after putting all that together.

You may also be interested in the walkdir crate.

1 Like

How to convert ReadDir structs in String or Path ??


&Path is to PathBuf as &str is to String. So:

let entry = a.unwrap();
let path_buf: PathBuf = a.path();
let path: &Path = &*path_buf;

Not all PathBufs (or &Paths) can be losslessly turned into Strings. Sometimes you can lossfully convert, but in your program, you want to stick with PathBuf / &Path because if you lossfully convert the PathBuf, your attempt to read_dir on it won't succeed (or might even succeed but on a different file entry that corresponds to the lossfully converted name).

1 Like

For the moment, this piece works for me.
Thanks a lot.

for a in fs::read_dir(dir)? {        
        let path = a?.path();
        // Get path string.
        let path_str = path.to_str().unwrap();
        let category = Path::new(path_str);
        //println!("{}", category.display());
        for b in fs::read_dir(category)? {
            println!("{:?}", b);
        } // end for b
    } //end for a