检查文件是否属于给定类型

Check if a file is of a given type

如何修复此功能?我认为我必须将名称转换为 String,但随后我必须将其转换回 str 才能使用 ends_with。我应该使用另一个函数来做到这一点吗?

use walkdir::{DirEntry};

fn is_filetype(entry: &DirEntry, _type: &str) -> bool {
    entry.file_name()
        .to_str()
        .to_lowercase()
        .map(|s| s.ends_with(_type))
        .unwrap_or(false)
}

error[E0599]: no method named `to_lowercase` found for enum `Option` in the current scope
  --> src/bin/parse_torrent.rs:45:10
   |
45 |         .to_lowercase()
   |          ^^^^^^^^^^^^ method not found in `Option<&str>`

修复问题中提供的代码的最简单方法可能是使用 map_or,就像@ChayimFriedman 在评论中建议的那样。

fn is_filetype(entry: &DirEntry, _type: &str) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, |s| s.to_lowercase().ends_with(_type))
}

但是,如果我们扩展它以查看其他方法,则还有更多选择。 过去,我使用的一种方法是使用内置的 .extension() 方法。

if path.extension().and_then(OsStr::to_str) == Some("txt") {
    do_the_thing();
}

不过,我们或许可以做得更好。经过一番修改后,这就是我的想法。

pub trait FileExtension {
    fn has_extension<S: AsRef<str>>(&self, extensions: &[S]) -> bool;
}

impl<P: AsRef<Path>> FileExtension for P {
    fn has_extension<S: AsRef<str>>(&self, extensions: &[S]) -> bool {
        if let Some(ref extension) = self.as_ref().extension().and_then(OsStr::to_str) {
            return extensions
                .iter()
                .any(|x| x.as_ref().eq_ignore_ascii_case(extension));
        }

        false
    }
}

这个新版本为我们提供了一些额外的功能。我们可以检查多种扩展类型,这让我们可以更灵活地选择它使用的类型。

// original
if is_filetype(&dir_entry, "txt") {}

// Alternate
if dir_entry.path().has_extension(&["txt"]) {}

// We can also check for multiple extensions
if dir_entry.path().has_extension(&["png", "jpg", "jpeg", "gif", "bmp"]) {}

也就是说,有一些 pros/cons:

  • 扩展名为 .tar.gz 的文件将被读取为扩展名为 gz
  • 名称以句点开头的文件不会被误读为扩展名(例如:文件夹 ~/.ssh 被正确识别为没有扩展名)。
  • 文件开头的“魔术字节”不会在需要时检查文件类型。