Find files with SQL-like queries
Find files with SQL-like queries
While it doesn't tend to fully replace traditional find and ls, fselect has these nice features:
.gitignore, .hgignore, and .dockerignore support (experimental)plocate and Everything indexes for lightning-fast searchMore is under way!
cargo install fselectYou can optionally build with fast, index-backed search support: voidtools Everything
on Windows (--features everything, then pass --everything) or plocate
on Linux (--features plocate, then pass --plocate). See the
usage guide for details.
AUR package, thanks to @asm0dey
AUR bin package, thanks to @4censord
fselect in nixpkgs, thanks to @filalex77
A precompiled binary
winget install -e --id fselect.fselectchoco install fselectscoop install fselectPrecompiled binaries are available at GitHub downloads (gunzip, then chmod +x fselect):
brew install fselectsudo port selfupdate
sudo port install fselectfselect [ARGS] COLUMN[, COLUMN...] [from ROOT[, ROOT...]] [where EXPR] [group by COLUMNS] [having EXPR] [order by COLUMNS] [limit N] [offset N] [into FORMAT]fselect -iDetailed description of all the supported features.
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 = *.tmpOr 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 0Specify 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 6mbMore 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 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-01Default 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 100Enable .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 2000Find square images:
fselect path from /home/user/Photos where width = heightFind images with a known name part but unknown extension:
fselect path from /home/user/projects where name = "*RDS*" and width gte 1Find 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 != falseEven 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_videoFind files with dangerous permissions:
fselect mode, path from /home/user where other_write or other_exec
fselect mode, path from /home/user where other_allSimple 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 != 1000Or by owner's or group's name:
fselect user, group, path from /home/user where user = mike or group = mikeFind 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_socketFind 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"Filter groups after aggregation:
fselect "ext, count(*) from /tmp group by ext having count(*) > 10"
fselect "sha256, count(*) from ~/Downloads group by sha256 having count(*) > 1"Order results:
fselect path from /tmp order by size desc, name
fselect modified, fsize, path from ~ order by 1 desc, 3Finally, 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 htmlMIT/Apache-2.0
Supported by JetBrains IDEA open source license
No open issues yet, or sync has not completed.