diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..ee51923 --- /dev/null +++ b/README.en.md @@ -0,0 +1,335 @@ +# fselect +Find files with SQL-like queries + +[![Crates.io](https://img.shields.io/crates/v/fselect.svg)](https://crates.io/crates/fselect) +[![build](https://github.com/jhspetersson/fselect/actions/workflows/rust.yml/badge.svg)](https://github.com/jhspetersson/fselect/actions/workflows/rust.yml) + +### Why use fselect? + +While it doesn't tend to fully replace traditional `find` and `ls`, **fselect** has these nice features: + +* SQL-like (not real SQL, but highly relaxed!) grammar easily understandable by humans +* complex queries, compare results in several directories with [subqueries](docs/usage.md#subqueries-for-in-and-exists) +* aggregate, statistics, date, and other [functions](docs/usage.md#functions) +* search within archives +* `.gitignore`, `.hgignore`, and `.dockerignore` support (experimental) +* search by width and height of images, EXIF metadata +* search by audio metadata (MP3, FLAC, Ogg Vorbis, Opus, M4A/AAC, WAV, AIFF, APE, WavPack, Musepack, Speex) +* search by extended file attributes, POSIX ACLs, and Linux capabilities +* search by file hashes +* search by MIME type +* shortcuts to common file types +* [interactive mode](docs/usage.md#interactive-mode) +* support for `plocate` and `Everything` indexes for lightning-fast search +* various output formatting (CSV, JSON, and others) + +More is under way! + +### Installation + +#### Latest release from source + +* Install [Rust with Cargo](https://www.rust-lang.org/en-US/install.html) and its dependencies to build a binary +* Run `cargo install fselect` + +You can optionally build with fast, index-backed search support: [voidtools *Everything*](https://www.voidtools.com/) +on Windows (`--features everything`, then pass `--everything`) or [*plocate*](https://plocate.sesse.net/) +on Linux (`--features plocate`, then pass `--plocate`). See the +[usage guide](docs/usage.md#index-backed-search-everything--plocate) for details. + +#### Debian/Ubuntu + +[deb package](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect_0.10.2-1_amd64.deb) + +#### Fedora/RHEL/openSUSE + +[rpm package](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-0.10.2-1.x86_64.rpm) + +#### Arch Linux + +[AUR package](https://aur.archlinux.org/packages/fselect/), thanks to [@asm0dey](https://github.com/asm0dey) + +[AUR bin package](https://aur.archlinux.org/packages/fselect-bin/), thanks to [@4censord](https://github.com/4censord) + +#### NixOS + +[`fselect` in `nixpkgs`](https://github.com/filalex77/nixpkgs/blob/1eced92263395896c10cea69e5f60e8be5f43aeb/pkgs/tools/misc/fselect/default.nix), thanks to [@filalex77](https://github.com/filalex77) + +#### Other Linux + +* x86_64: [glibc](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-x86_64-linux.gz) · [musl (static)](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-x86_64-linux-musl.gz) +* aarch64: [glibc](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-aarch64-linux.gz) · [musl (static)](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-aarch64-linux-musl.gz) + +#### Windows 64bit + +A precompiled [binary](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-x86_64-win.zip) + +#### Windows via winget + +* Install [winget](https://github.com/microsoft/winget-cli) +* Run `winget install -e --id fselect.fselect` + +#### Windows via Chocolatey + +* Install [Chocolatey](https://chocolatey.org/install) +* Run `choco install fselect` + +#### Windows via Scoop + +* Install [Scoop](https://scoop.sh) +* Run `scoop install fselect` + +#### macOS + +Precompiled binaries are available at GitHub downloads (`gunzip`, then `chmod +x fselect`): + +* [Intel (x86_64)](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-x86_64-mac.gz) +* [Apple Silicon (aarch64)](https://github.com/jhspetersson/fselect/releases/download/0.10.2/fselect-aarch64-mac.gz) + +#### Mac via Homebrew + +* Install [brew](https://brew.sh) +* Run `brew install fselect` + +#### Mac via MacPorts + +* Install [MacPorts](https://www.macports.org) +* Run: + ``` + sudo port selfupdate + sudo port install fselect + ``` + +### Usage + + fselect [ARGS] COLUMN[, COLUMN...] [from ROOT[, ROOT...]] [where EXPR] [group by COLUMNS] [order by COLUMNS] [limit N] [offset N] [into FORMAT] + +### Interactive mode + + fselect -i + +### Documentation + +[Detailed description of all the supported features.](docs/usage.md) + +### Examples + +Find temporary or config files (full path and size): + + fselect size, path from /home/user where name = '*.cfg' or name = '*.tmp' + +Windows users may omit the quotes: + + fselect size, path from C:\Users\user where name = *.cfg or name = *.tmp + +Or put all the arguments into the quotes like this: + + fselect "name from /home/user/tmp where size > 0" + +Search within a directory name with spaces (backticks are also supported): + + fselect "name from '/home/user/dir with spaces' where size > 0" + fselect "name from `/home/user/dir with spaces` where size > 0" + +Or simply escape the single quote: + + fselect name from \'/home/user/dir with spaces\' where size gt 0 + +Specify the file size, get an absolute path, and add it to the results: + + cd /home/user + fselect size, abspath from ./tmp where size gt 2g + fselect fsize, abspath from ./tmp where size = 5m + fselect hsize, abspath from ./tmp where size lt 8k + fselect name, size from ./tmp where size between 5mb and 6mb + +More complex query: + + fselect "name from /tmp where (name = *.tmp and size = 0) or (name = *.cfg and size > 1000000)" + +You can use subqueries: + + fselect "name from /test1 where size > 100 and size in (select size from /test2 where name in (select name from /test3 where modified in (select modified from /test4 where size < 200)))" + fselect "name, path, size from /data as data where exists (select * from /backup as backup where backup.name = data.name)" + +A subquery can also be used in the `FROM` clause as the source of the outer query: + + fselect "src.name, src.size from (select path from /projects depth 2 where size > 100) as src where src.name like '%.rs'" + +Aggregate functions (you can use curly braces if you want and even combine them with the regular parentheses): + + fselect "MIN(size), MAX{size}, AVG(size), SUM{size}, COUNT(*) from /home/user/Downloads" + +Formatting functions: + + fselect "LOWER(name), UPPER(name), LENGTH(name), YEAR(modified) from /home/user/Downloads" + +Get the year of the oldest file: + + fselect "MIN(YEAR(modified)) from /home/user" + +Use single quotes if you need to address files with spaces: + + fselect "path from '/home/user/Misc stuff' where name != 'Some file'" + +Regular expressions of [Rust flavor](https://docs.rs/regex/1.1.0/regex/#syntax) are supported: + + fselect name from /home/user where path =~ '.*Rust.*' + +Negate regular expressions: + + fselect "name from . where path !=~ '^\./config'" + +Simple globs expand automatically and work with `=` and `!=` operators: + + fselect name from /home/user where path = '*Rust*' + +Classic LIKE: + + fselect "path from /home/user where name like '%report-2018-__-__???'" + +Exact match operators to search with regexps disabled: + + fselect "path from /home/user where name === 'some_*_weird_*_name'" + +Find files by date: + + fselect path from /home/user where created = 2017-05-01 + fselect path from /home/user where modified = today + fselect path from /home/user where accessed = yesterday + fselect "path from /home/user where modified = 'apr 1'" + fselect "path from /home/user where modified = 'last fri'" + +Be more specific to match all files created at an interval between 3PM and 4PM: + + fselect path from /home/user where created = '2017-05-01 15' + +And even more specific: + + fselect path from /home/user where created = '2017-05-01 15:10' + fselect path from /home/user where created = '2017-05-01 15:10:30' + +Date and time intervals are possible (find everything updated since May 1st): + + fselect path from /home/user where modified gte 2017-05-01 + +Default is the current directory: + + fselect path, size where name = '*.jpg' + +Search within multiple locations: + + fselect path from /home/user/oldstuff, /home/user/newstuff where name = '*.jpg' + +With minimum and/or maximum depth specified (`depth` is a synonym for `maxdepth`): + + fselect path from /home/user/oldstuff depth 5 where name = '*.jpg' + fselect path from /home/user/oldstuff mindepth 2 maxdepth 5, /home/user/newstuff depth 10 where name = '*.jpg' + +Optionally follow symlinks: + + fselect path, size from /home/user symlinks where name = '*.jpg' + +Search within archives (currently only zip-archives are supported): + + fselect path, size from /home/user archives where name = '*.jpg' + +Or in combination: + + fselect size, path from /home/user depth 5 archives symlinks where name = '*.jpg' limit 100 + +Enable `.gitignore` or `.hgignore` support: + + fselect size, path from /home/user/projects gitignore where name = '*.cpp' + fselect size, path from /home/user/projects git where name = '*.cpp' + fselect size, path from /home/user/projects hgignore where name = '*.py' + +Search by image dimensions: + + fselect CONCAT(width, 'x', height), path from /home/user/photos where width gte 2000 or height gte 2000 + +Find square images: + + fselect path from /home/user/Photos where width = height + +Find images with a known name part but unknown extension: + + fselect path from /home/user/projects where name = "*RDS*" and width gte 1 + +Find old-school rap MP3 files: + + fselect duration, path from /home/user/music where genre = Rap and bitrate = 320 and mp3_year lt 2000 + +Shortcuts to common file extensions: + + fselect path from /home/user where is_archive = true + fselect path, mime from /home/user where is_audio = 1 + fselect path, mime from /home/user where is_book != false + +Even simpler way of using boolean columns: + + fselect path from /home/user where is_doc + fselect path from /home/user where is_image + fselect path from /home/user where is_video + +Find files with dangerous permissions: + + fselect mode, path from /home/user where other_write or other_exec + fselect mode, path from /home/user where other_all + +Simple glob-like expressions or even regular expressions in file mode are possible: + + fselect mode, path from /home/user where mode = '*rwx' + fselect mode, path from /home/user where mode =~ '.*rwx$' + +Find files by owner's uid or gid: + + fselect uid, gid, path from /home/user where uid != 1000 or gid != 1000 + +Or by owner's or group's name: + + fselect user, group, path from /home/user where user = mike or group = mike + +Find special files: + + fselect name from /usr/bin where suid + fselect path from /tmp where is_sticky + fselect path from /tmp where is_pipe + fselect path from /tmp where is_socket + +Find files with xattrs, check if a particular xattr exists, or get its value: + + fselect "path, has_xattrs, has_xattr(user.test), xattr(user.test) from /home/user" + +Include arbitrary text as columns: + + fselect "name, ' has size of ', size, ' bytes'" + +Group results: + + fselect "ext, count(*) from /tmp group by ext" + fselect "ext, count(*) from /tmp group by 1" + fselect "mime, ext, count(*) from /tmp group by 1, 2" + +Order results: + + fselect path from /tmp order by size desc, name + fselect modified, fsize, path from ~ order by 1 desc, 3 + +Finally, limit the results: + + fselect name from /home/user/samples limit 5 + +Format output: + + fselect size, path from /home/user limit 5 into json + fselect size, path from /home/user limit 5 into csv + fselect size, path from /home/user limit 5 into html + +### License + +MIT/Apache-2.0 + +--- + +Supported by [JetBrains IDEA](https://jb.gg/OpenSourceSupport) open source license