Walkdir: how to iterate and filter over all entries handling errors that may arise

I would like to iterate and filter entries with walkdir, handling errors that may arise.

The following code does not compile, I understand why (? is in a closure that returns &walkdir::DirEntry), but I hope it clarifies what I am trying to achieve...

use anyhow::Result;
use walkdir::WalkDir;

fn main() -> Result<()> {
    for entry in WalkDir::new(".")
        .into_iter()
        .map(|e| e?)
        .filter(|e| e.file_type().is_file())
    {
        println("{}", entry.path().display());
    }
    Ok(())
}

The following code works, but silently ignores any errors that may arise:

use anyhow::Result;
use walkdir::WalkDir;

fn main() -> Result<()> {
    for entry in WalkDir::new(".")
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| e.file_type().is_file())
    {
        println("{}", entry.path().display());
    }
    Ok(())
}

You can map each Result<F, E> to Result<Option<F>, E> and then transpose to Option<Result<F, E>>, allowing you to filter_map back to Result<F, E> without discarding errors.

fn main() -> Result<()> {
    for entry in WalkDir::new(".")
        .into_iter()
        .filter_map(|file| {
            file.map(|f| f.file_type().is_file().then(move || f))
                .transpose()
        })
    {
        let entry = entry?;
        println!("{}", entry.path().display());
    }
    Ok(())
}

Thanks for the hint, that's clever but looks a little hacky to me, so maybe in this case it's better to filter in the main function, as follows:

use anyhow::Result;
use walkdir::WalkDir;

fn main() -> Result<()> {
    for entry in WalkDir::new(".")
    {
        let entry = entry?;
        if entry.file_type().is_file() {
            println("{}", entry.path().display());
        }
    }
    Ok(())
}

Do you agree?