diff --git a/.idea/csv-plugin.xml b/.idea/csv-plugin.xml
new file mode 100644
index 0000000..4423c5a
--- /dev/null
+++ b/.idea/csv-plugin.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 9539096..9f6ef7a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -169,7 +169,7 @@ dependencies = [
[[package]]
name = "fif"
-version = "0.2.0"
+version = "0.2.1"
dependencies = [
"cached",
"clap",
diff --git a/Cargo.toml b/Cargo.toml
index d5ca04b..4782794 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "fif"
description = "A command-line tool for detecting and optionally correcting files with incorrect extensions."
-version = "0.2.0"
+version = "0.2.1"
authors = ["Lynnesbian "]
edition = "2018"
license = "GPL-3.0-or-later"
diff --git a/src/extensionset.rs b/src/extensionset.rs
new file mode 100644
index 0000000..c8bf4ba
--- /dev/null
+++ b/src/extensionset.rs
@@ -0,0 +1,24 @@
+use clap::Clap;
+
+#[derive(Clap, PartialEq, Debug)]
+pub enum ExtensionSet {
+ Images,
+ Audio,
+ Videos,
+ Media,
+ Documents,
+ Archives
+}
+
+impl ExtensionSet {
+ pub fn extensions(&self) -> Vec<&str> {
+ match self {
+ Self::Images => vec!["png", "jpg", "jpeg", "webp", "raw", "gif", "apng", "tga", "bmp", "tif", "tiff", "heif",
+ "avif", "jp2", "mng", "svg"],
+ Self::Videos => vec!["webm", "mp4", "mkv", "mov", "avi", "m4v", "wmv", "bik", "ogv", "qt", "3gp", "3g2", "divx"],
+ Self::Audio => vec!["ogg", "oga", "opus", "mp3", "m4a", "aac", "flac", "ape", "midi", "mid", "alac", "wav",
+ "aiff", "aa3", "at3"],
+ _ => todo!()
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/formats.rs b/src/formats.rs
index bb612c9..a391537 100644
--- a/src/formats.rs
+++ b/src/formats.rs
@@ -72,6 +72,7 @@ pub trait Format {
}
}
+// TODO: maybe make a batch script version for windows
pub struct Script {}
impl Format for Script {
@@ -89,9 +90,9 @@ impl Format for Script {
}
fn no_known_extension(&self, f: &mut W, path: &PathBuf) -> io::Result<()> {
- write!(f, "echo No known extension for ")?;
+ write!(f, "printf No known extension for ")?;
write_pathbuf(f, path)?;
- writeln!(f,)
+ writeln!(f,"\nprintf '\n'")
}
fn unreadable(&self, f: &mut W, path: &PathBuf) -> io::Result<()> {
@@ -109,12 +110,12 @@ impl Format for Script {
fn header(&self, _: &Entries, f: &mut W) -> io::Result<()> {
write!(
f,
- "#!/usr/bin/env sh\n\nGenerated by fif {}.\n\n",
+ "#!/usr/bin/env sh\n# Generated by fif {}.\n\nset -e\n\n",
VERSION.unwrap_or("???")
)
}
fn footer(&self, _: &Entries, f: &mut W) -> io::Result<()> {
- writeln!(f, "\necho Done.")
+ writeln!(f, "\nprintf 'Done.\\n'")
}
}
diff --git a/src/main.rs b/src/main.rs
index a7eab3d..04d0a41 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -37,6 +37,7 @@ mod inspectors;
mod mimedb;
mod parameters;
mod scanerror;
+mod extensionset;
#[cfg(feature = "infer-backend")]
static MIMEDB: OnceCell = OnceCell::new();
@@ -63,7 +64,7 @@ fn is_hidden(entry: &DirEntry) -> bool {
.map_or(false, |f| f.starts_with('.') && f != ".")
}
-fn wanted_file(args: ¶meters::Parameters, entry: &DirEntry) -> bool {
+fn wanted_file(args: ¶meters::Parameters, exts: &Vec<&str>, entry: &DirEntry) -> bool {
if !args.scan_hidden && is_hidden(entry) {
// skip hidden files and directories. this check is performed first because it's very lightweight.
return false;
@@ -80,11 +81,7 @@ fn wanted_file(args: ¶meters::Parameters, entry: &DirEntry) -> bool {
return false;
} // don't scan files without extensions. TODO - this should be configurable
- if let Some(extensions) = &args.extensions {
- // if the user has specified a list of extensions to check against, make sure this file ends in one of them.
- return extensions.contains(&ext.unwrap().to_lowercase().into());
- }
- true
+ exts.contains(&ext.unwrap().to_lowercase().as_str())
}
fn extension_from_path(path: &Path) -> Option {
@@ -179,9 +176,22 @@ fn main() {
debug!("Iterating directory: {:?}", args.dirs);
+ let extensions: Vec<&str> = if let Some(exts) = &args.exts {
+ exts
+ .iter()
+ .map(|s| s.as_str())
+ .collect()
+ } else if let Some(exts) = &args.ext_set {
+ exts.extensions().to_vec()
+ } else {
+ unreachable!()
+ };
+
+ debug!("Checking files with extensions: {:?}", extensions);
+
let stepper = WalkDir::new(&args.dirs).into_iter();
let entries: Vec = stepper
- .filter_entry(|e| wanted_file(&args, e)) // filter out unwanted files
+ .filter_entry(|e| wanted_file(&args, &extensions, e)) // filter out unwanted files
.filter_map(|e| e.ok()) // ignore anything that fails, e.g. files we don't have read access on
.filter(|e| !e.file_type().is_dir()) // remove directories from the final list
.collect();
diff --git a/src/parameters.rs b/src/parameters.rs
index bd398c5..5b9bc97 100644
--- a/src/parameters.rs
+++ b/src/parameters.rs
@@ -2,6 +2,7 @@ use std::path::PathBuf;
use clap::Clap;
use smartstring::{LazyCompact, SmartString};
+use crate::extensionset::ExtensionSet;
#[derive(Clap, PartialEq, Debug)]
pub enum OutputFormat {
@@ -12,8 +13,12 @@ pub enum OutputFormat {
#[derive(Clap, Debug)]
pub struct Parameters {
/// Only examine files with these extensions (Comma-separated list)
- #[clap(short, long, use_delimiter = true, require_delimiter = true)]
- pub extensions: Option>>,
+ #[clap(short, long, use_delimiter = true, require_delimiter = true, required_unless_present = "ext-set")]
+ pub exts: Option>>,
+
+ /// write good docs 0uo
+ #[clap(short = 'E', long, arg_enum, required_unless_present = "exts")]
+ pub ext_set: Option,
/// Don't skip hidden files and directories
#[clap(short, long)]