Repository: rust
Issue: [libs] add recursive variant of `fs::read_dir`
Labels: T-libs-api,C-feature-request

## Motivation

As part of the [`fs` module](https://doc.rust-lang.org/std/fs/index.html) there exist various recursive and non-recursive operations. `create_dir` and `create_dir_all`. `remove_dir` and `remove_dir_all`. But to read the contents of a directory there currently only exists [`read_dir`](https://doc.rust-lang.org/std/fs/fn.read_dir.html), but no recursive counterpart:

|Action Kind| Base function | Recursive variant
|---| -- | -- |
| Create a directory| `fs::create_dir` | `fs::create_dir_all` |
| Remove a directory | `fs::remove_dir` | `fs::remove_dir_all` |
| Read a directory's contents | `fs::read_dir` | ... |

I noticed the omission of this method when trying to read out a directory recursively, and discovered this was the only directory operation that doesn't have a recursive counterpart.

## Usage overview
I'd imagine `fs::read_dir_all` would be used in much the same way as `fs::read_dir`:

```rust
for entry in fs::read_dir_all(dir)? {
    let entry = entry?;
    dbg!(entry.path());
}
```

## Implementation overview
Roughly the API additions to `std::fs` would look like this:
```rust
#[derive(Debug)]
pub struct ReadDirAll;

impl Iterator for ReadDirAll {
    type Item = Result<DirEntry>;
}

pub fn read_dir_all<P: AsRef<Path>>(path: P) -> Result<ReadDirAll>;
```

## Potential drawbacks

I remember reading something about the [`readdir(3)` syscall](https://linux.die.net/man/3/readdir), and a file filtering as part of the kernel. But I can't seem to find any reference to that anymore. I also thought this had been referenced in a prior RFC, but that too I cannot find.

But for argument's sake, even if there was a variant for `readdir` variant that took a filter I'd argue that since `std::fs::read_dir` doesn't provide filtering, neither should `std::fs_read_dir_all`. And if we'd want a variant that *does* provide filtering, it would not be a clean counterpart to `fs::read_dir`, so it would warrant introducing under a new name.

These functions should be able to co-exist with each other, much the same way `fs::read_to_string` and `io::Read::read_to_string` co-exist (both useful, but is a simplified version of the other).

## Similar functionality in other languages

- __C++__ has [`std::filesystem::recursive_directory_iterator`](https://en.cppreference.com/w/cpp/filesystem/recursive_directory_iterator) since C++ 17.
- __nodejs__ doesn't include this as part of core, but the [readdirp](https://www.npmjs.com/package/readdirp) package in userland has [over half a billion](https://img.shields.io/npm/dt/readdirp.svg?style=flat-square) downloads indicating there's interest in this functionality.
- __bash__ has the `find` command generally available. `$ find .` will recursively print out all directory contents.
- And more entries can be found as part of [rosetta code](https://rosettacode.org/wiki/Walk_a_directory/Recursively).

## Conclusion
I think `fs::read_dir_all` makes for a straight forward addition to the stdlib. People expect this functionality to exist by default, and the shape and name of this function doesn't seem controversial. Even if filtering supersets of this functionality could possibly exist, they would likely be a different shape, and could co-exist with this function. Thanks!