Давайте шаг за шагом пройдемся по цепочке.
fs::read_dir(dir)?
создает дескриптор чтения в каталог, немедленно распространяет случай Err
, если это происходит, а если нет, unwrap
sуспех (это оператор ?
)
.into_iter()
превращает этот дескриптор чтения в итератор Result<DirEntry>
.map(|x|
x.map(|entry| entry.path())
)
Это вызывает метод path()
для каждого элементаитератор, если результат является действительным DirEntry
.Поскольку элемент итератора Result<DirEntry>
, а не просто DirEntry
, второй map()
позволяет вам разобраться с этим чисто.У вас остались пути, которые вы видите на выходе
.collect()
превращает этот итератор обратно в структуру, определяемую подсказками типов (здесь - вектор)
Может быть реализована фильтрующая частьдо или после вызова map()
, чтобы превратить запись в PathBuf
.Если вам нужно фильтровать по самому элементу, а не по PathBuf
, фильтруйте перед ним.Если вы можете фильтровать на основе PathBuf
, фильтруйте после него.
Использование функции комбинатора filter()
не вызывает затруднений - вы закрываете ее, она будет применяться к каждому элементу.Если возврат закрытия равен true
, элемент сохраняется.Если значение равно false, элемент удаляется.
Вот пример для возврата только каталогов:
fn folders(dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
Ok(fs::read_dir(dir)?
.into_iter()
.filter(|r| r.is_ok()) // Get rid of Err variants for Result<DirEntry>
.map(|r| r.unwrap().path()) // This is safe, since we only have the Ok variants
.filter(|r| r.is_dir()) // Filter out non-folders
.collect())
}