added some extension sets, replaced 'echo' with 'printf' in shell output

This commit is contained in:
Lynne Megido 2021-02-18 21:43:24 +10:00
parent fc7af85ba1
commit df2f924b2f
Signed by: lynnesbian
GPG key ID: F0A184B5213D9F90
7 changed files with 78 additions and 15 deletions

23
.idea/csv-plugin.xml Normal file
View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CsvFileAttributes">
<option name="attributeMap">
<map>
<entry key="/src/main.rs">
<value>
<Attribute>
<option name="separator" value="&#9;" />
</Attribute>
</value>
</entry>
<entry key="/src/parameters.rs">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
</map>
</option>
</component>
</project>

2
Cargo.lock generated
View file

@ -169,7 +169,7 @@ dependencies = [
[[package]] [[package]]
name = "fif" name = "fif"
version = "0.2.0" version = "0.2.1"
dependencies = [ dependencies = [
"cached", "cached",
"clap", "clap",

View file

@ -1,7 +1,7 @@
[package] [package]
name = "fif" name = "fif"
description = "A command-line tool for detecting and optionally correcting files with incorrect extensions." description = "A command-line tool for detecting and optionally correcting files with incorrect extensions."
version = "0.2.0" version = "0.2.1"
authors = ["Lynnesbian <lynne@bune.city>"] authors = ["Lynnesbian <lynne@bune.city>"]
edition = "2018" edition = "2018"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"

24
src/extensionset.rs Normal file
View file

@ -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!()
}
}
}

View file

@ -72,6 +72,7 @@ pub trait Format {
} }
} }
// TODO: maybe make a batch script version for windows
pub struct Script {} pub struct Script {}
impl Format for Script { impl Format for Script {
@ -89,9 +90,9 @@ impl Format for Script {
} }
fn no_known_extension<W: Write>(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { fn no_known_extension<W: Write>(&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)?; write_pathbuf(f, path)?;
writeln!(f,) writeln!(f,"\nprintf '\n'")
} }
fn unreadable<W: Write>(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { fn unreadable<W: Write>(&self, f: &mut W, path: &PathBuf) -> io::Result<()> {
@ -109,12 +110,12 @@ impl Format for Script {
fn header<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> { fn header<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
write!( write!(
f, 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("???") VERSION.unwrap_or("???")
) )
} }
fn footer<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> { fn footer<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
writeln!(f, "\necho Done.") writeln!(f, "\nprintf 'Done.\\n'")
} }
} }

View file

@ -37,6 +37,7 @@ mod inspectors;
mod mimedb; mod mimedb;
mod parameters; mod parameters;
mod scanerror; mod scanerror;
mod extensionset;
#[cfg(feature = "infer-backend")] #[cfg(feature = "infer-backend")]
static MIMEDB: OnceCell<mimedb::InferDb> = OnceCell::new(); static MIMEDB: OnceCell<mimedb::InferDb> = OnceCell::new();
@ -63,7 +64,7 @@ fn is_hidden(entry: &DirEntry) -> bool {
.map_or(false, |f| f.starts_with('.') && f != ".") .map_or(false, |f| f.starts_with('.') && f != ".")
} }
fn wanted_file(args: &parameters::Parameters, entry: &DirEntry) -> bool { fn wanted_file(args: &parameters::Parameters, exts: &Vec<&str>, entry: &DirEntry) -> bool {
if !args.scan_hidden && is_hidden(entry) { if !args.scan_hidden && is_hidden(entry) {
// skip hidden files and directories. this check is performed first because it's very lightweight. // skip hidden files and directories. this check is performed first because it's very lightweight.
return false; return false;
@ -80,11 +81,7 @@ fn wanted_file(args: &parameters::Parameters, entry: &DirEntry) -> bool {
return false; return false;
} // don't scan files without extensions. TODO - this should be configurable } // don't scan files without extensions. TODO - this should be configurable
if let Some(extensions) = &args.extensions { exts.contains(&ext.unwrap().to_lowercase().as_str())
// 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
} }
fn extension_from_path(path: &Path) -> Option<String> { fn extension_from_path(path: &Path) -> Option<String> {
@ -179,9 +176,22 @@ fn main() {
debug!("Iterating directory: {:?}", args.dirs); 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 stepper = WalkDir::new(&args.dirs).into_iter();
let entries: Vec<DirEntry> = stepper let entries: Vec<DirEntry> = 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_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 .filter(|e| !e.file_type().is_dir()) // remove directories from the final list
.collect(); .collect();

View file

@ -2,6 +2,7 @@ use std::path::PathBuf;
use clap::Clap; use clap::Clap;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::extensionset::ExtensionSet;
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
pub enum OutputFormat { pub enum OutputFormat {
@ -12,8 +13,12 @@ pub enum OutputFormat {
#[derive(Clap, Debug)] #[derive(Clap, Debug)]
pub struct Parameters { pub struct Parameters {
/// Only examine files with these extensions (Comma-separated list) /// Only examine files with these extensions (Comma-separated list)
#[clap(short, long, use_delimiter = true, require_delimiter = true)] #[clap(short, long, use_delimiter = true, require_delimiter = true, required_unless_present = "ext-set")]
pub extensions: Option<Vec<SmartString<LazyCompact>>>, pub exts: Option<Vec<SmartString<LazyCompact>>>,
/// write good docs 0uo
#[clap(short = 'E', long, arg_enum, required_unless_present = "exts")]
pub ext_set: Option<ExtensionSet>,
/// Don't skip hidden files and directories /// Don't skip hidden files and directories
#[clap(short, long)] #[clap(short, long)]