added some extension sets, replaced 'echo' with 'printf' in shell output
This commit is contained in:
parent
fc7af85ba1
commit
df2f924b2f
7 changed files with 78 additions and 15 deletions
23
.idea/csv-plugin.xml
Normal file
23
.idea/csv-plugin.xml
Normal 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="	" />
|
||||||
|
</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
2
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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
24
src/extensionset.rs
Normal 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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -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: ¶meters::Parameters, entry: &DirEntry) -> bool {
|
fn wanted_file(args: ¶meters::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: ¶meters::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();
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
Loading…
Reference in a new issue