# fif ![A screenshot demonstrating fif's ability to detect the correct file extensions for a few files. ](https://gitlab.com/Lynnesbian/fif/-/raw/master/doc/screenshot.png) [![Version](https://img.shields.io/crates/v/fif.svg?logo=rust&style=flat-square) ](https://crates.io/crates/fif) [![Minimum Supported Rust Version](https://img.shields.io/badge/msrv-1.54.0-orange?logo=rust&style=flat-square) ](https://gitlab.com/Lynnesbian/fif/-/blob/master/README.md#version-policy) [![License](https://img.shields.io/crates/l/fif.svg?style=flat-square) ](https://gitlab.com/Lynnesbian/fif/-/blob/master/LICENSE) [![Build status](https://img.shields.io/gitlab/pipeline/Lynnesbian/fif/master?logo=gitlab&style=flat-square) ](https://gitlab.com/Lynnesbian/fif/-/pipelines/latest) [![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg?style=flat-square) ](https://github.com/rust-secure-code/safety-dance/) [![Dependency versions](https://deps.rs/repo/gitlab/lynnesbian/fif/status.svg) ](https://deps.rs/repo/gitlab/lynnesbian/fif) [![REUSE status](https://api.reuse.software/badge/gitlab.com/Lynnesbian/fif/) ](https://api.reuse.software/info/gitlab.com/Lynnesbian/fif/) *A command-line tool for detecting and optionally correcting files with incorrect extensions.*
fif recursively scans the given directory and outputs a shell script to fix the name of any files with incorrect extensions. By default, fif will scan all non-hidden files in the given directory, and will ignore symlinks. As fif prints a shell script to stdout rather than acting on the files directly, you may wish to redirect its output to a file, e.g. `fif ~/Documents > output.sh`. You can also pipe the output directly into your shell, e.g. `fif ~/Documents | bash`, although this is not recommended - you should look over fif's output and verify for yourself that it won't do anything that will give you a headache before running it. ## Features - :white_check_mark: Cross platform - :white_check_mark: Multi-threaded - :white_check_mark: Configurable ## Building fif can be built, installed, and tested with [Cargo], as with most rust programs: ```bash git clone https://gitlab.com/Lynnesbian/fif/ cd fif # run tests (optional) cargo test --locked # build fif with its default feature set cargo build --locked --release ``` The `--locked` flag ensures that Cargo uses the dependency versions specified in [the lock file](https://gitlab.com/Lynnesbian/fif/-/blob/master/Cargo.lock), and the `--release` flag builds fif with release optimisations enabled -- this takes longer, but produces a much faster binary. ### Installing ```bash # install the fif crate (to ~/.cargo/bin or %USERPROFILE%\.cargo\bin by default) cargo install --locked fif ``` To update, simply re-run the `install` command, or use a tool like [cargo-update ](https://github.com/nabijaczleweli/cargo-update), which can update crates installed via `cargo install`. On macOS, `fif` can be installed through [MacPorts](https://www.macports.org): ```bash sudo port selfupdate sudo port install fif ``` ### Cargo Features fif supports using [`infer`] or [`xdg-mime`] as its backend for looking up file types. By default, xdg-mime will be used on [*nix systems](https://en.wikipedia.org/wiki/Unix-like) (Linux, macOS, *BSD, etc.), and infer on all other systems. `xdg-mime` should work on any *nix system with the [Shared MIME Info] library installed (consult your package manager), although I've only tested it on Linux and FreeBSD. `infer` should work on any system, but it supports far fewer file types than `xdg-mime` does, thanks to the excellent Shared MIME Info library. You can override the default backend for your system at compile time like so: ```bash # xdg-mime cargo install fif --locked --features=xdg-mime-backend # infer cargo install fif --locked --features=infer-backend ``` It is also possible to get a more minimal build by installing without default features: ```bash cargo install fif --locked --no-default-features ``` This will disable some non-essential but nice to have features, like multi-threading support. For more info on fif's compile-time features, see [the wiki](https://gitlab.com/Lynnesbian/fif/-/wikis/Cargo-Features). ## Usage See `fif --help` for more. ### The basics The simplest way to use fif looks like this: ```bash fif ~/Downloads ``` This command will scan all non-hidden files in your `~/Downloads` directory. The `-e` and `-E` flags can be used to specify individual extensions and sets of extensions to scan, respectively: ```bash # only scan files with the extensions .jpeg, .jpg, .zip, and .docx fif -e jpeg,jpg,zip,docx ~/Documents # only scan files with "image extensions" - .jpg, .png, .gif, .webp... fif -E images ~/Pictures # scan .zip files, videos, and audio fif -e zip -E videos,audio ~/Downloads ``` Both `-e` and `-E` have equivalent `-x` and `-X` flags that exclude the given extensions rather than including them: ```bash # scan everything except filenames ending in .zip fif -x zip ~/Downloads # scan all files with image extensions, but not .jpg and .jpeg files fif -x jpg,jpeg -E images ~/Pictures # scan everything except text and system files fif -X text,system ~/.local/share ``` ### Output By default, fif will output a bash script (or PowerShell script on Windows) that can be used to fix all the files it found with incorrect file extensions. You might find it useful to output this script to a file (rather than to stdout): ```bash fif ~/Documents > output.sh ``` You can also manually specify an output format to use: ```bash fif -O powershell ~/Documents > output.ps1 ``` #### The `--fix` flag If, however, you'd rather have fif fix the misnamed files itself, rather than relying on a shell script, you can use the `--fix` flag: ```bash # rename any misnamed .jpg files in the user's pictures directory fif ~/Pictures --fix -e jpg # fix any misnamed files found in the user's downloads fif ~/Downloads --fix ``` By default, fif will avoid taking any potentially destructive actions (renaming a file to a name that already exists). This behaviour can be disabled with the `--overwrite` flag, which will instead prompt you to overwrite the existing file. fif will also prompt you to retry on errors. For more information on how the `--fix` flag works, and how it behaves in conjunction with the `--overwrite` flag and `--prompt` parameter, see [the corresponding wiki page](https://gitlab.com/Lynnesbian/fif/-/wikis/Fix). ### Logging By default, fif will log any info, warnings, and errors encountered during execution. This can be changed with the `-v` flag: ```bash # also log debug info fif -v ~/Downloads # ...and trace info fif -vv ~/Downloads ``` You can also reduce the level of logging with the `-q` flag: ```bash # don't show info fif -q ~/Downloads # ...or warnings fif -qq ~/Downloads # ...or even errors! fif -qqq ~/Downloads ``` The verbosity of the logging can also be modified by setting the environment variable `FIF_LOG` or `RUST_LOG` to `off`, `trace`, `debug`, `info`, `warn`, or `error`. Values set by `FIF_LOG` override `RUST_LOG`, and both override the `-v` and `-q` flags. For example: ```bash # show all levels except trace FIF_LOG=debug fif ~/Downloads # only show errors FIF_LOG=error fif ~/Downloads ``` The five logging levels are used as follows: | Level | Description | Example | |-|-|-| | error | Errors that cause fif to stop running | fif was unable to open the provided directory | | warn | Warnings that don't cause fif to stop running | fif was unable to determine the MIME type of a given file | | info | Information pertaining to fif's status | The provided directory was scanned without issue, and no files are in need of renaming | | debug | Debug information - usually not important to end users | The list of extensions fif will consider | | trace | Trace info - usually not important to end users | "Found 15 items to check", "Scan successful", etc. | For a more comprehensive explanation of all of fif's parameters and how to use them, run `fif --help` (or `fif -h` for a more concise overview). [Cargo]: https://doc.rust-lang.org/cargo/ [`xdg-mime`]: https://crates.io/crates/xdg-mime [`infer`]: https://crates.io/crates/infer [Shared MIME Info]: https://gitlab.freedesktop.org/xdg/shared-mime-info/ ## Version policy fif adheres to the [semantic versioning](https://semver.org/) principles. While fif remains at version 0.x, the version number will be updated as follows: - The MAJOR version will be bumped to 1 when I believe fif to be "feature complete". - The MINOR version will be bumped whenever I add a fairly important feature to fif (in the past, this has been bumped when adding the ability to exclude extensions, and when fif gained the ability to output a bash script rather than a list of invalid filenames). The MINOR version will also be bumped when increasing the MSRV. - The PATCH version will be bumped in all other cases, including minor feature additions (in the past, this has occurred when adding features such as more output formats and the "ignore unknown extensions" flag). If/when fif hits version 1.0, these rules will likely remain the same as they are now. ## Code style fif is formatted with `rustfmt` using a nightly toolchain, specifically with the command `cargo +nightly fmt`. Tabs are used for indentation, and are assumed to be two spaces wide. Lines are 120 characters wide. Braces are placed on the same line (["OTBS"](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)) format), except in the case of `where` clauses in generic parameters. For more detailed information on the formatting rules used by this project, see the configured options in [`rustfmt.toml`](https://gitlab.com/Lynnesbian/fif/-/blob/master/rustfmt.toml). ## Additional credits Some of the code for correctly handling files with multiple valid extensions (particularly in the case of the Portable Executable format) comes from [Czkawka](https://github.com/qarmin/czkawka) ## License Copyright (C) 2021 Lynnesbian This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .