walkdir

repository·master·Indexed 23 days ago

https://github.com/burntsushi/walkdir

A cross-platform Rust library for efficient recursive directory traversal. Version 2.5.0 provides features such as symbolic link following, control over open file descriptors via `max_open`, and efficient directory tree pruning using `filter_entry`. It includes the `WalkDir` builder for configuring depth, sorting, and filesystem boundaries, and the `DirEntry` struct for accessing file paths, metadata, and inode numbers on Unix systems.

Tokens
4.7K
Snippets
13
Records
21
Agent score
79%

What's inside walkdir

  1. How WalkDir and IntoIter work together

    master

    The WalkDir type acts as a builder. You use it to configure traversal options (depth, symlinks, sorting, etc.). Once configured, you call .into_iter() to consume the builder and produce an IntoIter instance.

    IntoIter is the actual iterator that performs the traversal. It implements Iterator<Item = Result<DirEntry>>. Because it returns a Result, you must handle potential I/O errors during the loop.

  2. Handle symbolic links with DirEntry

    master

    When walking directories, you may need to distinguish between symbolic links and their targets.

    • path_is_symlink(): Returns true if the entry was created from a symbolic link. This result is unaffected by the follow_links setting of the iterator. If this returns true, the path() method returns the name of the symbolic link.
    • To resolve the actual target path of a symbolic link, combine path_is_symlink() with std::fs::read_link():
    if entry.path_is_symlink() {
        let target = std::fs::read_link(entry.path())?;
        println!("Link target: {:?}", target);
    }
  3. Follow symbolic links during traversal

    master

    By default, walkdir does not follow symbolic links. To enable following them, call .follow_links(true) on the WalkDir builder.

    use walkdir::WalkDir;
    
    for entry in WalkDir::new("foo").follow_links(true) {
        let entry = entry.unwrap();
        println!("{}", entry.path().display());
    }
  4. Efficiently prune directory entries with filter_entry

    master

    To skip specific files or entire directories efficiently (preventing the walker from even descending into them), use the filter_entry iterator adapter. This is more efficient than filtering entries after they have been yielded, as it prunes the tree during traversal.

    use walkdir::{DirEntry, WalkDir};
    
    fn is_hidden(entry: &DirEntry) -> bool {
        entry.file_name()
             .to_str()
             .map(|s| s.starts_with("."))
             .unwrap_or(false)
    }
    
    let walker = WalkDir::new("foo").into_iter();
    for entry in walker.filter_entry(|e| !is_hidden(e)) {
        let entry = entry.unwrap();
        println!("{}", entry.path().display());
    }
  5. Recursively iterate over a directory

    master

    Use WalkDir::new("path") to create a new walker. You can iterate over the entries using a for loop. Note that each iteration returns a Result<DirEntry, Error>, so you must handle potential errors (e.g., using .unwrap() or pattern matching).

    use walkdir::WalkDir;
    
    for entry in WalkDir::new("foo") {
        let entry = entry.unwrap();
        println!("{}", entry.path().display());
    }
  6. Iterate over entries while ignoring errors

    master

    If you want to skip entries that cause errors (such as directories where the process lacks permission), use .into_iter().filter_map(|e| e.ok()) on the WalkDir instance.

    use walkdir::WalkDir;
    
    for entry in WalkDir::new("foo").into_iter().filter_map(|e| e.ok()) {
        println!("{}", entry.path().display());
    }
  7. Minimum Rust version requirements

    master
    The minimum supported rustc version for walkdir is 1.60.0. The project follows a policy where minor version updates (e.g., 1.0.z) maintain the same minimum requirement, but minor version increments (e.g., 1.y where y > 0) may increase the minimum required Rust version.
  8. Efficiently skip hidden files and directories using filter_entry

    master

    To avoid descending into specific directories (like hidden ones), use the .filter_entry() iterator adapter. This is more efficient than standard filter() because it prevents the iterator from even recursing into directories that fail the predicate.

    use walkdir::{DirEntry, WalkDir};
    
    fn is_hidden(entry: &DirEntry) -> bool {
        entry.file_name()
             .to_str()
             .map(|s| s.starts_with("."))
             .unwrap_or(false)
    }
    
    let walker = WalkDir::new("foo").into_iter();
    for entry in walker.filter_entry(|e| !is_hidden(e)) {
        println!("{}", entry?.path().display());
    }
    use walkdir::{DirEntry, WalkDir};
    # use walkdir::Error;
    
    fn is_hidden(entry: &DirEntry) -> bool {
        entry.file_name()
             .to_str()
             .map(|s| s.starts_with("."))
             .unwrap_or(false)
    }
    
    # fn try_main() -> Result<(), Error> {
    let walker = WalkDir::new("foo").into_iter();
    for entry in walker.filter_entry(|e| !is_hidden(e)) {
        println!("{}", entry?.path().display());
    }
    # Ok(())
    # }
  9. Follow symbolic links with WalkDir

    master

    By default, symbolic links are not followed. To follow them, use the .follow_links(true) method on the WalkDir builder. Note that if a symbolic link is broken or involved in a loop, an error will be yielded.

    use walkdir::WalkDir;
    
    for entry in WalkDir::new("foo").follow_links(true) {
        println!("{}", entry?.path().display());
    }
    use walkdir::WalkDir;
    # use walkdir::Error;
    
    # fn try_main() -> Result<(), Error> {
    for entry in WalkDir::new("foo").follow_links(true) {
        println!("{}", entry?.path().display());
    }
    # Ok(())
    # }
  10. Ignore errors during iteration

    master

    If you want to iterate over all entries and silently skip any errors (such as directories you do not have permission to access), use filter_map on the iterator produced by into_iter().

    use walkdir::WalkDir;
    
    for entry in WalkDir::new("foo").into_iter().filter_map(|e| e.ok()) {
        println!("{}", entry.path().display());
    }
  11. Basic recursive directory traversal with WalkDir

    master

    Use WalkDir::new(path) to create a builder for a recursive directory iterator. The iterator yields entries in depth-first order, with directories yielded before their contents. Each iteration returns a Result<DirEntry>, so you should handle potential errors (e.g., permission issues) during iteration.

    use walkdir::WalkDir;
    
    for entry in WalkDir::new("foo") {
        let entry = entry.unwrap();
        println!("{}", entry.path().display());
    }
    use walkdir::WalkDir;
    # use walkdir::Error;
    
    # fn try_main() -> Result<(), Error> {
    for entry in WalkDir::new("foo") {
        println!("{}", entry?.path().display());
    }
    # Ok(())
    # }