fselect Documentation

Find files with SQL-like queries

4,435 stars Rust Rust 1 file ยท ~26,522 tokens #cli#command-line#files#filesystem#find#hacktoberfest#query#rust
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy fselect on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name fselect --restart always jhspetersson/fselect:latest

File: README.md

fselect

Find files with SQL-like queries


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
  • aggregate, statistics, date, and other 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
  • 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 and its dependencies to build a binary
  • Run cargo install fselect

You 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.

Debian/Ubuntu

deb package

Fedora/RHEL/openSUSE

rpm package

Arch Linux

AUR package, thanks to @asm0dey

AUR bin package, thanks to @4censord

NixOS

fselect in nixpkgs, thanks to @filalex77

Other Linux

Windows 64bit

A precompiled binary

Windows via winget

  • Install winget
  • Run winget install -e --id fselect.fselect

Windows via Chocolatey

Windows via Scoop

  • Install Scoop
  • Run scoop install fselect

macOS

Precompiled binaries are available at GitHub downloads (gunzip, then chmod +x fselect):

Mac via Homebrew

  • Install brew
  • Run brew install fselect

Mac via MacPorts

  • Install MacPorts
  • Run:
    text
    sudo port selfupdate
    sudo port install fselect

Usage

text
fselect [ARGS] COLUMN[, COLUMN...] [from ROOT[, ROOT...]] [where EXPR] [group by COLUMNS] [having EXPR] [order by COLUMNS] [limit N] [offset N] [into FORMAT]

Interactive mode

text
fselect -i

Documentation

Detailed description of all the supported features.

Examples

Find temporary or config files (full path and size):

text
fselect size, path from /home/user where name = '*.cfg' or name = '*.tmp'

Windows users may omit the quotes:

text
fselect size, path from C:\Users\user where name = *.cfg or name = *.tmp

Or put all the arguments into the quotes like this:

text
fselect "name from /home/user/tmp where size > 0"

Search within a directory name with spaces (backticks are also supported):

text
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:

text
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:

text
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:

text
fselect "name from /tmp where (name = *.tmp and size = 0) or (name = *.cfg and size > 1000000)"

You can use subqueries:

text
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:

text
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):

text
fselect "MIN(size), MAX{size}, AVG(size), SUM{size}, COUNT(*) from /home/user/Downloads"

Formatting functions:

text
fselect "LOWER(name), UPPER(name), LENGTH(name), YEAR(modified) from /home/user/Downloads"

Get the year of the oldest file:

text
fselect "MIN(YEAR(modified)) from /home/user"

Use single quotes if you need to address files with spaces:

text
fselect "path from '/home/user/Misc stuff' where name != 'Some file'"

Regular expressions of Rust flavor are supported:

text
fselect name from /home/user where path =~ '.*Rust.*'

Negate regular expressions:

text
fselect "name from . where path !=~ '^\./config'"

Simple globs expand automatically and work with = and != operators:

text
fselect name from /home/user where path = '*Rust*'

Classic LIKE:

text
fselect "path from /home/user where name like '%report-2018-__-__???'"

Exact match operators to search with regexps disabled:

text
fselect "path from /home/user where name === 'some_*_weird_*_name'"

Find files by date:

text
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:

text
fselect path from /home/user where created = '2017-05-01 15'

And even more specific:

text
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):

text
fselect path from /home/user where modified gte 2017-05-01

Default is the current directory:

text
fselect path, size where name = '*.jpg'

Search within multiple locations:

text
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):

text
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:

text
fselect path, size from /home/user symlinks where name = '*.jpg'

Search within archives (currently only zip-archives are supported):

text
fselect path, size from /home/user archives where name = '*.jpg'

Or in combination:

text
fselect size, path from /home/user depth 5 archives symlinks where name = '*.jpg' limit 100

Enable .gitignore or .hgignore support:

text
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:

text
fselect CONCAT(width, 'x', height), path from /home/user/photos where width gte 2000 or height gte 2000

Find square images:

text
fselect path from /home/user/Photos where width = height

Find images with a known name part but unknown extension:

text
fselect path from /home/user/projects where name = "*RDS*" and width gte 1

Find old-school rap MP3 files:

text
fselect duration, path from /home/user/music where genre = Rap and bitrate = 320 and mp3_year lt 2000

Shortcuts to common file extensions:

text
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:

text
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:

text
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:

text
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:

text
fselect uid, gid, path from /home/user where uid != 1000 or gid != 1000

Or by owner's or group's name:

text
fselect user, group, path from /home/user where user = mike or group = mike

Find special files:

text
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:

text
fselect "path, has_xattrs, has_xattr(user.test), xattr(user.test) from /home/user"

Include arbitrary text as columns:

text
fselect "name, ' has size of ', size, ' bytes'"

Group results:

text
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:

text
fselect "ext, count(*) from /tmp group by ext having count(*) > 10"
fselect "sha256, count(*) from ~/Downloads group by sha256 having count(*) > 1"

Order results:

text
fselect path from /tmp order by size desc, name
fselect modified, fsize, path from ~ order by 1 desc, 3

Finally, limit the results:

text
fselect name from /home/user/samples limit 5

Format output:

text
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 open source license


File: docs/usage.md

fselect

Find files with SQL-like queries.

Basic usage
Restrictions
Columns and fields
File naming terminology
Functions
File size units
Search roots
Operators
Arithmetic operators
Subqueries in the FROM clause
Subqueries for IN and EXISTS
Date and time specifiers
Regular expressions
MIME and file types
Audio support
File hashes
Output formats
Configuration file
Bash completion
Command-line arguments
Index-backed search
Interactive mode
Environment variables
Exit values

Basic usage

text
fselect [ARGS] COLUMN[, COLUMN...] [from ROOT[, ROOT...]] [where EXPR] [group by COLUMNS] [having EXPR] [order by COLUMNS] [limit N] [offset N] [into FORMAT]

You write an SQL-like query, that's it.

fselect command itself is like a first keyword (select, i.e., file select).
But if you put one more select behind occasionally, that's not a problem.

Next you put columns you are interested in. It could be a file name or path, size, modification date, etc.
See the full list of possible columns. You can add columns with arbitrary text (put in quotes if it contains spaces).
A few functions (aggregating and formatting) are there for your service. You can use arithmetic expressions when it makes sense.

Where to search? Specify with from keyword. You can list one or more directories separated with comma.
If you leave the from, then current directory will be processed.

What to search? Use where with any number of conditions.

Group results with group by followed by one or more columns. Like order by, this clause
accepts positional numeric shortcuts that refer to columns from the select list, for example
group by 1 or group by 1, 2. An aggregate function in the select list is not required:
select ext from /home/user group by ext returns one row per distinct extension, like
SELECT DISTINCT in SQL.

Filter the groups themselves with having, which runs after aggregation
(while where filters individual files before it):

text
fselect ext, count(*) from /home/user group by ext having count(*) > 10
fselect "ext, sum(size) from /home/user group by ext having sum(size) > 100mb"
fselect "ext, count(*) as c from /home/user group by ext having c > 10 order by c desc"
fselect "sha256, count(*) from /home/user/Downloads group by sha256 having count(*) > 1"

A having condition may use aggregate functions (even ones not in the select list),
grouping columns, select-list aliases, and and/or/not logic. Referencing a
non-grouping column outside an aggregate is an error, as in SQL. With aggregation but no
group by, the whole result set forms one implicit group, and having decides whether the
single result row is returned at all. Subqueries (in, exists) are not supported inside
having yet.

Order results like in real SQL with order by. All columns are supported for ordering by,
as well as asc/desc parameters and positional numeric shortcuts.

Limiting search results is possible with limit and offset. Formatting options are supported with into keyword.

If you want to use operators containing > or <,
put the whole query into the double quotes.
This will protect a query from the shell and output redirection.
The same applies to queries with parentheses or *, ? and other special shell
metacharacters.

It's ok to use any metacharacters in interactive mode.

It's not a real SQL

Directories to search at are listed with comma separators.
In a real SQL, such syntax would make a cross-product. Here it means just search at A, next at B, and so on.

You can use curly braces instead of the regular parentheses! This helps to avoid a few of the shell pitfalls a little bit.
Functions with no arguments don't require parentheses at all.

String literals don't really need quotes.
You will need to put them just in case you query something with spaces inside.
And yes, you should use quotes for glob-patterns or regular expressions in the query
on Linux or macOS to prevent parameter expansion from the shell.
If you are on Windows, feel free to omit most of the quotes.

Commas for column separation aren't needed as well. Column aliasing (with or without as keyword) is not supported.

where section can contain short syntax conditions for boolean columns (like is_audio or other_write).

into keyword specifies output format, not output table.

Joins and unions are not supported (yet?).
Subqueries have only limited support: in IN / EXISTS predicates, and as the source of a FROM clause.

Columns and fields

Column Meaning Comment
name Returns the name (with extension) of the file
filename or fname Returns the file name without extension
extension or ext Returns the extension of the file
path Returns the relative path of the file
abspath Returns the absolute path of the file
directory or dirname or dir Returns the directory of the file
absdir Returns the absolute directory of the file
size Returns the size of the file in bytes
fsize or hsize Returns the size of the file accompanied with the unit
uid Returns the UID of the owner
gid Returns the GID of the owner's group
accessed Returns the time the file was last accessed (YYYY-MM-DD HH:MM:SS)
created Returns the file creation date (YYYY-MM-DD HH:MM:SS) Windows, macOS, and Linux (kernel 4.11+ with ext4/btrfs/XFS)
modified Returns the time the file was last modified (YYYY-MM-DD HH:MM:SS)
atime Returns the last access time as a Unix timestamp (seconds since epoch) Available only on Unix
atime_nsec Returns the nanosecond component of the last access time Available only on Unix
mtime Returns the last modification time as a Unix timestamp (seconds since epoch) Available only on Unix
mtime_nsec Returns the nanosecond component of the last modification time Available only on Unix
ctime Returns the last status change time as a Unix timestamp (seconds since epoch) Available only on Unix
ctime_nsec Returns the nanosecond component of the last status change time Available only on Unix
is_dir Returns a boolean signifying whether the file path is a directory
is_file Returns a boolean signifying whether the file path is a file
is_symlink Returns a boolean signifying whether the file path is a symlink
link_target or symlink_target Returns the target path of the symlink, or an empty value if the file is not a symlink
is_broken_symlink or is_broken_link Returns a boolean signifying whether the file path is a symlink whose target does not exist
is_pipe or is_fifo Returns a boolean signifying whether the file path is a FIFO or pipe file
is_char or is_character Returns a boolean signifying whether the file path is a character device or character special file
is_block Returns a boolean signifying whether the file path is a block or block special file
is_socket Returns a boolean signifying whether the file path is a socket file
is_hidden Returns a boolean signifying whether the file is a hidden file (e.g., files that start with a dot on *nix)
has_xattrs Returns a boolean signifying whether the file has extended attributes or alternate data streams on Windows
xattr_count Returns the count of extended attributes on the file or alternate data streams on Windows
extattrs Returns the extended file attributes as a string of flag letters (chattr/lsattr flags on Linux, NTFS attribute letters on Windows) Available only on Linux and Windows
has_extattrs Returns a boolean signifying whether the file has any extended file attributes set Available only on Linux and Windows
acl Returns all ACL entries in standard form (POSIX on Linux, DACL on Windows) Available only on Linux and Windows
has_acl Returns a boolean signifying whether the file has POSIX ACL entries beyond standard Unix permissions or Windows explicit ACEs Available only on Linux and Windows
default_acl Returns all default ACL entries in standard form (default POSIX ACLs on Linux, inheritable ACEs on Windows) Available only on Linux and Windows
has_default_acl Returns a boolean signifying whether the directory has default ACL entries (default POSIX ACLs on Linux, inheritable ACEs on Windows) Available only on Linux and Windows
has_capabilities or has_caps Returns a boolean signifying whether the file has capabilities Available only on Linux
capabilities or caps Returns a string describing Linux capabilities assigned to a file Available only on Linux
device Returns the code of device the file is stored on Available only on Unix
rdev Returns the device ID for special files (character and block devices) Available only on Unix
inode Returns the number of inode Available only on Linux
blocks Returns the number of blocks (512 bytes) the file occupies Available only on Linux
blksize or block_size Returns the preferred block size for filesystem I/O in bytes Available only on Unix
hardlinks Returns the number of hardlinks of the file Available only on Linux
mode Returns the permissions of the owner, group, and everybody (similar to the first field in ls -la)
user Returns the name of the owner for this file Available only on *nix platforms with users feature enabled
user_read Returns a boolean signifying whether the file can be read by the owner
user_write Returns a boolean signifying whether the file can be written by the owner
user_exec Returns a boolean signifying whether the file can be executed by the owner
user_all Returns a boolean signifying whether the file can be fully accessed by the owner
group Returns the name of the owner's group for this file Available only on *nix platforms with users feature enabled
group_read Returns a boolean signifying whether the file can be read by the owner's group
group_write Returns a boolean signifying whether the file can be written by the owner's group
group_exec Returns a boolean signifying whether the file can be executed by the owner's group
group_all Returns a boolean signifying whether the file can be fully accessed by the group
other_read Returns a boolean signifying whether the file can be read by others
other_write Returns a boolean signifying whether the file can be written by others
other_exec Returns a boolean signifying whether the file can be executed by others
other_all Returns a boolean signifying whether the file can be fully accessed by the others
suid or is_suid Returns a boolean signifying whether the file permissions have a SUID bit set
sgid or is_sgid Returns a boolean signifying whether the file permissions have a SGID bit set
sticky or is_sticky Returns a boolean signifying whether the file permissions have a sticky bit set
width Returns the number of pixels along the width of the photo or MP4 file
height Returns the number of pixels along the height of the photo or MP4 file
mime Returns MIME type of the file
is_binary Returns a boolean signifying whether the file has binary contents
is_text Returns a boolean signifying whether the file has text contents
line_count Returns a number of lines in a text file
word_count or words Returns the number of whitespace-separated words in a text file
char_count or chars Returns the number of characters in a text file
encoding Returns the detected text encoding of the file (e.g., ASCII, UTF-8, UTF-16LE), or an empty value for binary files
has_bom Returns a boolean signifying whether the file begins with a byte-order mark (BOM)
line_ending or line_endings or eol Returns the line ending style of a text file (LF, CRLF, CR, Mixed, or empty)
exif_datetime Returns date and time of taken photo
exif_datetime_original or exif_dto Returns original date and time when the photo was taken
exif_altitude or exif_alt Returns GPS altitude of taken photo
exif_latitude or exif_lat Returns GPS latitude of taken photo
exif_longitude or exif_lng or exif_lon Returns GPS longitude of taken photo
exif_make Returns name of the camera manufacturer
exif_model Returns camera model
exif_software Returns software name with which the photo was taken
exif_version Returns the version of EXIF metadata
exif_exposure_time or exif_exptime Returns exposure time of the photo taken
exif_aperture Returns aperture value of the photo taken
exif_shutter_speed Returns shutter speed of the photo taken
exif_f_number or exif_f_num Returns F-number of the photo taken
exif_iso_speed or exif_iso Returns ISO speed of the photo taken (EXIF 2.3 ISOSpeed tag)
exif_sensitivity or exif_photo_sensitivity Returns photographic sensitivity (ISO) of the photo taken
exif_focal_length or exif_focal_len Returns focal length of the photo taken
exif_lens_make Returns lens manufacturer used to take the photo
exif_lens_model Returns lens model used to take the photo
exif_description or exif_desc Returns image description from EXIF metadata
exif_artist Returns the artist or photographer name
exif_copyright Returns the copyright information
exif_orientation Returns the image orientation
exif_flash Returns the flash status when the photo was taken
exif_color_space Returns the color space of the image
exif_exposure_program or exif_exp_program Returns the exposure program used
exif_exposure_bias or exif_exp_bias Returns the exposure bias value
exif_white_balance or exif_wb Returns the white balance mode
exif_metering_mode Returns the metering mode
exif_scene_type or exif_scene Returns the scene capture type
exif_contrast Returns the contrast setting
exif_saturation Returns the saturation setting
exif_sharpness Returns the sharpness setting
exif_body_serial or exif_serial Returns the camera body serial number
exif_lens_serial Returns the lens serial number
exif_user_comment or exif_comment Returns the user comment from EXIF metadata
exif_image_width or exif_width Returns the image width from EXIF metadata
exif_image_height or exif_height Returns the image height from EXIF metadata
exif_max_aperture Returns the max aperture value of the lens
exif_digital_zoom or exif_dzoom Returns the digital zoom ratio
mp3_title or title Returns the title of the audio file taken from the file's metadata
mp3_album or album Returns the album name of the audio file taken from the file's metadata
mp3_artist or artist Returns the artist of the audio file taken from the file's metadata
mp3_genre or genre Returns the genre of the audio file taken from the file's metadata
mp3_comment or comment Returns the comment of the audio file taken from the file's metadata
mp3_track or track Returns the track number of the audio file taken from the file's metadata (e.g., 4 or 4/9)
mp3_disc or disc Returns the disc number (part of a set) of the audio file taken from the file's metadata (e.g., 1 or 1/2)
mp3_year or audio_year Returns the year of the audio file taken from the file's metadata
mp3_freq or freq Returns the sampling rate of the audio file in Hz
mp3_bitrate or bitrate Returns the bitrate of the audio file in kbps
duration Returns the duration in seconds of an audio file, or an MP4/Matroska/WebM video
is_shebang Returns a boolean signifying whether the file starts with a shebang (#!)
is_git_repo Returns a boolean signifying whether the directory contains a .git subdirectory or file
is_git_tracked or git_tracked Returns a boolean signifying whether the file is tracked by git Requires the git feature (enabled by default)
is_gitignored or is_git_ignored Returns a boolean signifying whether the file is ignored by git Requires the git feature (enabled by default)
git_status Returns the git status of the file (clean, modified, staged, untracked, conflicted, or ignored) Requires the git feature (enabled by default)
git_branch Returns the current branch of the git repository containing the file Requires the git feature (enabled by default)
git_last_commit_hash or git_commit_hash Returns the hash of the last commit that touched the file Requires the git feature (enabled by default)
git_last_commit_date or git_commit_date Returns the date of the last commit that touched the file Requires the git feature (enabled by default)
git_last_commit_author or git_commit_author Returns the author of the last commit that touched the file Requires the git feature (enabled by default)
is_empty Returns a boolean signifying whether the file is empty or the directory is empty
is_archive Returns a boolean signifying whether the file is an archival file default extensions
is_audio Returns a boolean signifying whether the file is an audio file default extensions
is_book Returns a boolean signifying whether the file is a book default extensions
is_doc Returns a boolean signifying whether the file is a document default extensions
is_font Returns a boolean signifying whether the file is a font default extensions
is_image Returns a boolean signifying whether the file is an image default extensions
is_source Returns a boolean signifying whether the file is source code default extensions
is_video Returns a boolean signifying whether the file is a video file default extensions
sha1 Returns SHA-1 digest of a file
sha2_256 or sha256 Returns SHA2-256 digest of a file
sha2_512 or sha512 Returns SHA2-512 digest of a file
sha3_512 or sha3 Returns SHA-3 digest of a file

File naming terminology

Let's see how all these are different:

text
fselect abspath, absdir, path, dir, name, filename, ext from /home/user/projects where is_file
Column Value Comment
abspath /home/user/projects/foobar/content/readme.md Absolute path includes everything
absdir /home/user/projects/foobar/content Absolute directory includes everything except the last segment
path foobar/content/readme.md Path is relative to the search root /home/user/projects
dir foobar/content Relative directory
name readme.md name = filename + ext
filename readme
ext md

Functions

Aggregate functions

Queries using these functions return only one result row.

Function Meaning Example
AVG Average of all values select avg(size) from /home/user/Downloads
COUNT Number of rows; count(col) skips rows with empty values select count(*) from /home/user/Downloads
MAX Maximum value (numeric, date, or string) select max(size) from /home/user/Downloads
MIN Minimum value (numeric, date, or string) select min(size) from /home/user where size gt 0
SUM Sum of all values select sum(size) from /home/user/Downloads
STDDEV_POP, STDDEV or STD Population standard deviation, the square root of variance select stddev_pop(size) from /home/user/Downloads
STDDEV_SAMP Sample standard deviation, the square root of sample variance select stddev_samp(size) from /home/user/Downloads
VAR_POP or VARIANCE Population variance select var_pop(size) from /home/user/Downloads
VAR_SAMP Sample variance select var_samp(size) from /home/user/Downloads

Date functions

Used mostly for formatting results.

Function Meaning Example
CURRENT_DATE or CUR_DATE or CURDATE Returns current date select modified, path where modified = CURDATE()
CURRENT_TIME or CUR_TIME or CURTIME Returns current local time (HH:MM:SS) select CURRENT_TIME()
CURRENT_TIMESTAMP or NOW Returns current local timestamp (YYYY-MM-DD HH:MM:SS) select NOW()
DAY Extract day of the month select day(modified) from /home/user/Downloads
MONTH Extract month of the year select month(name) from /home/user/Downloads
YEAR Extract year of the date select year(name) from /home/user/Downloads
DOW or DAYOFWEEK Returns day of the week (1 - Sunday, 2 - Monday, etc.) select name, modified, dow(modified) from /home/user/projects/FizzBuzz
DAYNAME Returns the name of the day of the week select dayname(modified) from /home/user/Downloads
DOY or DAYOFYEAR Returns the day of the year (1-366) select dayofyear(modified) from /home/user/Downloads
DATE_ADD or DATEADD Add days to a date select "date_add(modified, 30) from /home/user"
DATE_SUB or DATESUB Subtract days from a date select "date_sub(modified, 7) from /home/user"
DATE_DIFF or DATEDIFF Number of days between two dates select "date_diff(modified, created) from /home/user"
FROM_UNIXTIME Convert a Unix timestamp to a datetime string select "from_unixtime(mtime) from /home/user"
LAST_DAY or LAST_DATE Last day of the month for a given date select "last_day(modified) from /home/user"
EXTRACT Extract a date/time part (year, quarter, month, week, day, hour, minute, second, dow, isodow, doy, epoch) โ€” unit must be quoted select "extract('year', modified) from /home/user"
DATE_TRUNC or DATETRUNC Truncate a date to a unit (year, quarter, month, week, day, hour, minute, second) โ€” unit must be quoted select "date_trunc('month', modified) from /home/user"

User functions

These are only available on Unix platforms when users feature has been enabled during compilation.

Function Meaning Example
CURRENT_UID Current real UID select CURRENT_UID()
CURRENT_USER Current real UID's name select CURRENT_USER()
CURRENT_GID Current primary GID select CURRENT_GID()
CURRENT_GROUP Current primary GID's name select CURRENT_GROUP()

Xattr functions

Used to check if a particular xattr exists or to get its value.
Supported platforms are Linux, macOS, FreeBSD, and NetBSD.

Function Meaning Example
HAS_XATTR Check if xattr exists select "name, has_xattr(user.test) from /home/user"
XATTR Get value of xattr select "name, xattr(user.test) from /home/user"
HAS_EXTATTR Check if a specific extended file attribute flag is set (Linux and Windows) select "name from / where has_extattr('i')"
HAS_ACL_ENTRY Check if a specific ACL entry exists (Linux and Windows) select "name from /data where has_acl_entry('user:john')"
ACL_ENTRY Get permissions of a specific ACL entry (Linux and Windows) select "name, acl_entry('group:staff') from /data"
HAS_DEFAULT_ACL_ENTRY Check if a specific default ACL entry exists (Linux and Windows) select "name from /data where has_default_acl_entry('user:john')"
DEFAULT_ACL_ENTRY Get permissions of a specific default ACL entry (Linux and Windows) select "name, default_acl_entry('group:staff') from /data"
HAS_CAPABILITY or HAS_CAP Check if given Linux capability exists for the file select "name, has_cap('cap_bpf') from /home/user"

ACLs

fselect can read and display Access Control Lists on both Linux and Windows.

POSIX ACLs (Linux)

On Linux, fselect reads POSIX Access Control Lists stored as system.posix_acl_access or system.posix_acl_default
extended attributes. It is useful for auditing file permissions beyond the standard Unix owner/group/other model.

The has_acl field returns true when a file has extended ACL entries (named users, named groups,
or a mask entry) beyond the basic owner/group/other permissions.

The acl field returns all ACL entries in standard getfacl-like format, comma-separated:
user::rwx,user:john:rw-,group::r-x,group:staff:r--,mask::rwx,other::r--

Use has_acl_entry and acl_entry to query specific entries. The entry specifier uses the format
type:qualifier where type is user (or u), group (or g), mask (or m), or other (or o).
An empty qualifier refers to the owning user/group. Examples:

text
fselect name from /data where has_acl = true
fselect "name, acl from /data where has_acl = true"
fselect "name from /data where has_acl_entry('user:john')"
fselect "name, acl_entry('group:staff') from /data"

When the users feature is enabled, uid/gid values are resolved to usernames/group names.
Otherwise, numeric IDs are used in the output.

Windows DACLs

On Windows, fselect reads the Discretionary Access Control List (DACL) via the Win32 Security API.
Only explicit (non-inherited) ACEs are shown.

The has_acl field returns true when a file has at least one explicit (non-inherited) ACE in its DACL.

The acl field returns all explicit ACEs as comma-separated entries in the format
type:trustee:permissions, where:

  • type is allow or deny
  • trustee is the resolved account name (e.g., BUILTIN\Administrators, NT AUTHORITY\SYSTEM)
  • permissions is one of full, modify, rx, read, write, or a hex value for non-standard masks

Example output: allow:BUILTIN\Administrators:full,allow:NT AUTHORITY\SYSTEM:full,allow:BUILTIN\Users:rx

The default_acl and has_default_acl fields report a directory's inheritable ACEs (those
carrying the object- or container-inherit flag), which are the Windows analogue of POSIX default
ACLs โ€” the entries that propagate to newly created child objects.

Use has_acl_entry and acl_entry (and their default_acl_entry counterparts) to query a
single trustee. The argument is matched against the trustee either as a full DOMAIN\Name or as
a bare account name, case-insensitively:

text
fselect name from C:\ where has_acl = true
fselect "name, acl from C:\Users where has_acl = true"
fselect "name, default_acl from C:\Windows where is_dir = true"
fselect "name from C:\data where has_acl_entry('Administrators')"
fselect "name, acl_entry('BUILTIN\Users') from C:\data"

Extended file attributes

fselect can read and query extended file attributes (also known as file flags). On Linux these
are the flags managed with chattr and displayed with lsattr, read via the FS_IOC_GETFLAGS
ioctl on ext2/ext3/ext4, btrfs, and other supporting filesystems. On Windows these are the NTFS
file attributes.

On Linux the extattrs field returns a string of flag letters for each set attribute, using the
same single-letter codes as lsattr/chattr:
s (secure deletion), u (undelete), c (compress), S (synchronous updates),
i (immutable), a (append only), d (no dump), A (no atime updates),
E (encrypted), I (indexed directory), j (journal data), t (no tail-merging),
D (dirsync), T (top of directory hierarchy), e (extents), V (verity),
C (no copy-on-write), x (DAX), N (inline data), P (project hierarchy),
F (case-insensitive directory).

On Windows the extattrs field returns a string of letters for each set NTFS attribute
(letters follow the attrib command where applicable):
R (read-only), H (hidden), S (system), A (archive), T (temporary),
P (sparse file), L (reparse point), C (compressed), O (offline),
I (not content indexed), E (encrypted), V (integrity stream).
Note that the Windows letters are case-sensitive (all upper-case).

The has_extattrs field returns true when any of these attributes are set.
Use the has_extattr() function to check for a specific flag:

text
fselect name from / where has_extattrs = true
fselect "name, extattrs from /data where has_extattrs = true"
fselect "name from / where has_extattr('i')"
fselect "name, extattrs from C:\data where has_extattr('H')"

String functions

Used mostly for formatting results.

Function Meaning Example
LENGTH or LEN Length of string value select length(name) from /home/user/Downloads order by 1 desc limit 10
LOWER or LOWERCASE or LCASE Convert value to lowercase select lower(name) from /home/user/Downloads
UPPER or UPPERCASE or UCASE Convert value to uppercase select upper(name) from /home/user/Downloads
INITCAP Returns first letter of each word uppercase, all other letters lowercase select initcap('MICHAEL SMITH')
TO_BASE64 or BASE64 Encode value to Base64 select base64(name) from /home/user/Downloads
FROM_BASE64 Decode value from Base64 select from_base64('ZnNlbGVjdCByb2Nrcw==')
CONCAT Returns concatenated string of expression values select CONCAT('Name is ', name, ' size is ', fsize, '!!!') from /home/user/Downloads
CONCAT_WS Returns concatenated string of expression values with specified delimiter select name, fsize, CONCAT_WS('x', width, height) from /home/user/Images
LOCATE or POSITION (str, substr, pos) Returns position of substr in str value (optionally starting from pos) select locate('foo', 'barfoo')
SUBSTRING or SUBSTR (str, pos, len) Part of str value starting from pos of (optionally) len characters long. Negative pos means starting pos characters from the end of the string. select substr(name, 1, 8) from /home/user/Downloads
REPLACE (str, from, to) Replace all occurrences of from by to select replace(name, metallica, MetaLLicA) from /home/user/Music/Rock
TRIM Returns string with whitespaces at the beginning and the end stripped select trim(title), trim(artist), trim(album) from /home/user/Music into json
LTRIM Returns string with whitespaces at the beginning stripped select ltrim(title) from /home/user/Music into json
RTRIM Returns string with whitespaces at the end stripped select rtrim(title) from /home/user/Music into json

Japanese string functions

Used for detecting Japanese symbols in file names and such.

Function Meaning Example
CONTAINS_JAPANESE or JAPANESE Check if string value contains Japanese symbols select japanese(name) from /home/user/Downloads
CONTAINS_KANA or KANA Check if string value contains kana symbols select kana(name) from /home/user/Downloads
CONTAINS_HIRAGANA or HIRAGANA Check if string value contains hiragana symbols select contains_hiragana(name) from /home/user/Downloads
CONTAINS_KATAKANA or KATAKANA Check if string value contains katakana symbols select katakana(name) from /home/user/Downloads
CONTAINS_KANJI or KANJI Check if string value contains kanji symbols select kanji(name) from /home/user/Downloads

Greek string functions

Used for detecting Greek symbols in file names and such.

Function Meaning Example
CONTAINS_GREEK or GREEK Check if string value contains Greek symbols select greek(name) from /home/user/Downloads

Other functions

Function Meaning Example
BIN Convert integer value to binary representation select name, size, bin(size) from /home/user/Downloads
HEX Convert integer value to hexadecimal representation select name, size, hex(size), upper(hex(size)) from /home/user/Downloads
OCT Convert integer value to octal representation select name, size, oct(size) from /home/user/Downloads
ABS Returns absolute value of the expression select abs(-5)
POWER or POW Raise the value to the specified power select pow(2, 3)
SQRT Returns square root of the value select sqrt(25)
LOG Returns logarithm of the value select log(1000)
LN Returns natural logarithm of the value select ln(10)
EXP Returns Euler's number raised to the power of the value select exp(2)
LEAST Returns the smallest of the expression values select least(1, 2, 3)
GREATEST Returns the largest of the expression values select greatest(1, 2, 3)
PI Returns pi (ฯ€) constant select pi()
FLOOR Returns the largest integer less than or equal to the value select floor(2.5)
CEIL or CEILING Returns the smallest integer greater than or equal to the value select ceil(2.5)
ROUND Returns the value rounded to the nearest integer, or to a given number of decimal places select round(2.5) or select round(pi(), 2)
CONTAINS true if file contains string, false if not select contains(TODO) from /home/user/Projects/foo/src
COALESCE Returns first nonempty expression value select name, size, COALESCE(sha256, '---') from /home/user/Downloads
RANDOM or RAND Returns random integer (from zero to max int, from zero to arg, or from arg1 to arg2) select path from /home/user/Music order by RAND()
FORMAT_TIME or PRETTY_TIME Returns human-readable durations of time in seconds like 2min 26s select format_time(duration) from /home/user/Music
FORMAT_SIZE Returns formatted size of a file select name, FORMAT_SIZE(size, '%.0') from /home/user/Downloads order by size desc limit 10

Let's try FORMAT_SIZE with different format specifiers:

Specifier Meaning Output
format_size(1678123) Default output 1.60MiB
format_size(1678123, ' ') Put a space before units 1.60 MiB
format_size(1678123, '%.0') Round up decimal part 2MiB
format_size(1678123, '%.1') One place for decimal part 1.6MiB
format_size(1678123, '%.2') Two places for decimal part 1.60MiB
format_size(1678123, '%.2 ') Two places for decimal part, and put a space before units 1.60 MiB
format_size(1678123, '%.2 d') Use decimal divider, e.g. 1000-based units, not 1024-based 1.68 MB
format_size(1678123, '%.2 c') Use conventional format, e.g. 1024-based divider, but display 1000-based units 1.60 MB
format_size(1678123, '%.2 k') Display file size in specified unit, this time in kibibytes 1638.79 KiB
format_size(1678123, '%.2 ck') What is a kibibyte? Gimme conventional unit! 1638.79 KB
format_size(1678123, '%.0 ck') And drop this decimal part! 1639 KB
format_size(1678123, '%.0 kb') Use 1000-based kilobyte 1678 KB
format_size(1678123, '%.0kb') Don't put a space 1678KB
format_size(1678123, '%.0s') Use short units 2M
format_size(1678123, '%.0 s') Use short units with a space 2 M

File size units

Specifier Meaning Bytes
t or tib tebibyte 1024 * 1024 * 1024 * 1024
tb terabyte 1000 * 1000 * 1000 * 1000
g or gib gibibyte 1024 * 1024 * 1024
gb gigabyte 1000 * 1000 * 1000
m or mib mebibyte 1024 * 1024
mb megabyte 1000 * 1000
k or kib kibibyte 1024
kb kilobyte 1000
text
fselect size, path from /home/user/tmp where size gt 2g
fselect fsize, path from /home/user/tmp where size = 5mib
fselect hsize, path from /home/user/tmp where size lt 8kb

Search roots

text
path [option N] [option] [option] [option...][, path2 [option...]]

When you put a directory to search at, you can specify some options.

Option Meaning
mindepth N Minimum search depth. Default is unlimited. Depth 1 means skip one directory level and search further.
maxdepth N Maximum search depth. Default is unlimited. Depth 1 means search the mentioned directory only. Depth 2 means search mentioned directory and its subdirectories. Synonym is depth.
symlinks If specified, search process will follow symlinks. Default is not to follow. Synonym is sym.
archives Search within archives. Only zip archives are supported. Default is not to include archived content into the search results. Synonym is arc.
gitignore Search respects .gitignore files found. Synonym is git.
hgignore Search respects .hgignore files found. Synonym is hg.
dockerignore Search respects .dockerignore files found. Synonym is dock.
nogitignore Disable .gitignore parsing during the search. Synonym is nogit.
nohgignore Disable .hgignore parsing during the search. Synonym is nohg.
nodockerignore Disable .dockerignore parsing during the search. Synonym is nodock.
dfs Depth-first search mode.
bfs Breadth-first search mode. This is the default.
regexp Use regular expressions to search within multiple roots. Synonym is rx.

Operators

  • = or == or eq
  • != or <> or ne
  • === or eeq
  • !== or ene
  • > or gt
  • >= or gte or ge
  • < or lt
  • <= or lte or le
  • =~ or ~= or regexp or rx
  • !=~ or !~= or notrx
  • like
  • notlike
  • between
  • in
  • exists

Arithmetic operators

Operator Alias
+ plus
- minus
* mul
/ div
% mod

Subqueries in the `FROM` clause

The FROM clause can take a parenthesized inner query in place of (or alongside) a filesystem path.
The inner query is executed first, and the rows it produces become the input set the outer query
iterates over โ€” its WHERE, SELECT, LIMIT, and ORDER BY clauses then run against that set
without any further directory traversal.

sql
select name from (select * from /projects depth 2)

You can attach options like an alias to the subselect root just like a regular root:

sql
select src.name, src.size from (select path from /projects depth 2) as src where src.size > 1024

A WHERE clause inside the subselect filters the input set; a WHERE clause outside filters the
outer rows produced from that input set:

sql
select name from (select path from /projects depth 2 where size > 100) where name like '%.rs'

Subselects may be nested.

Subqueries for `IN` and `EXISTS`

Subqueries in fselect allow you to nest queries within queries, enabling powerful file search operations that compare results across different directory trees.
Subqueries can be used with the IN, NOT IN, EXISTS, and NOT EXISTS operators to create sophisticated filtering logic.

Important: When using subqueries that need to reference the parent query's results, you must bind search roots using aliases with the AS keyword.
This creates a correlated subquery where the inner query can reference columns from the outer query.

[!CAUTION]
This feature is still in development. Random queries can fail for no obvious reason.

General Subquery Syntax

sql
SELECT columns FROM root AS alias
WHERE column operator (SELECT columns2 FROM root2 AS alias2 WHERE condition)

Supported Operators

  • IN - Tests if a value exists in the subquery result set
  • NOT IN - Tests if a value does not exist in the subquery result set
  • EXISTS - Tests if the subquery returns any rows
  • NOT EXISTS - Tests if the subquery returns no rows

`IN` Operator

The IN operator checks if a value from the outer query matches any value returned by the subquery.

Example: Find files in /backup that have the same size as files in /production:

sql
select name, size from /backup 
where size in (select size from /production)

Example: Find files with multiple levels of correlation:

sql
select 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
    )
  )
)

This query finds files in /test1 where:

  1. Size is greater than 100 bytes
  2. Size matches files in /test2
  3. Those /test2 files have names matching files in /test3
  4. Those /test3 files have modification times matching files in /test4 (smaller than 200 bytes)

Example: Find files in /home/user/docs where the filename appears in subdirectories with the same extension:

sql
select name, path from /home/user/docs as parent
where name in (
  select name from /home/user/docs/archive as child
  where child.ext = parent.ext
)

The as parent and as child aliases allow the subquery to reference the outer query's ext column.

`NOT IN` Operator

The NOT IN operator checks if a value from the outer query does NOT match any value in the subquery.

Example: Find files in /current that don't exist in /backup (by name):

sql
select name, path from /current
where name not in (select name from /backup)

Example: Find config files that exist in production but not in staging:

sql
select name, path from /production/config as prod
where name not in (
  select name from /staging/config where ext = 'cfg'
)

Example: Find files unique to a directory by both name and size:

sql
select name, size, path from /home/user/projects as proj
where name not in (
  select name from /home/user/archive as arch
  where arch.size = proj.size
)

Important Note: NOT IN can produce unexpected results if the subquery returns any NULL/empty values.
When in doubt, use NOT EXISTS instead (see below).

`EXISTS` Operator

The EXISTS operator returns true if the subquery returns at least one row.
It's often more efficient than IN and handles NULL/empty values better.

Example: Find directories that contain image files:

sql
select path from /home/user as parent
where is_dir and exists (
  select * from /home/user as child
  where child.dir = parent.path and child.is_image
)

Example: Find files in /data that have a backup in /backup with the same name:

sql
select name, path, size from /data as data
where exists (
  select * from /backup as backup
  where backup.name = data.name
)

Example: Find directories that have been modified recently (contain files modified in the last 7 days):

sql
select path from /home/user/projects gitignore as proj
where is_dir 
  and exists (
      select * from /home/user/projects as files
      where is_file 
        and files.dir = proj.abspath 
        and files.modified >= 'last week'
  )

`NOT EXISTS` Operator

The NOT EXISTS operator returns true if the subquery returns zero rows. This is the safest way to check for non-matching data.

Example: Find files in /production that don't have a backup:

sql
select name, path from /production as prod
where not exists (
  select * from /backup as backup
  where backup.name = prod.name
)

Example: Find files in /cache that don't have corresponding source files:

sql
select name, path from /cache as cache
where not exists (
  select * from /source as source
  where source.name = cache.name
    and source.size > 0
)

Example: Find source files that have no corresponding test files:

sql
select name, path from /home/user/src as src
where ext = 'rs' and not exists (
  select * from /home/user/tests as tests
  where tests.name like concat(src.name, '_test%')
    and tests.ext = 'rs'
)

Unix timestamps

The atime, mtime, and ctime fields return raw Unix timestamps (seconds since epoch) as integers.
These are available only on Unix platforms and are useful when you need numeric comparison
or want to pass exact values to external tools.

text
fselect name, mtime from /home/user/projects
fselect name, atime from /home/user where atime gt 1700000000
fselect "name, format_time(mtime) from /home/user"
fselect "name, day(accessed), mtime from /home/user"

Unlike accessed, modified, and created which return formatted date/time strings,
these fields return the raw integer value from the filesystem metadata.

The companion atime_nsec, mtime_nsec, and ctime_nsec fields return the sub-second
nanosecond component of the respective timestamp, for cases where second-level precision
is not enough.

text
fselect name, mtime, mtime_nsec from /home/user/projects

Git fields

The git fields look up the repository containing each file (the nearest enclosing work tree)
and report per-file information. git_status returns one of clean, modified, staged,
untracked, conflicted, or ignored. The git_last_commit_* fields walk the repository
history to find the last commit that touched the file, like git log -1 -- path, so they are
relatively expensive on large histories.

text
fselect name, git_status from /home/user/projects/repo where git_status = modified
fselect path from /home/user/projects/repo where is_git_tracked = false and is_gitignored = false
fselect name, git_last_commit_date, git_last_commit_author from src
fselect path, git_branch from /home/user/projects where is_git_repo = true depth 2

is_git_repo simply checks for a .git subdirectory (or file) and is available in every build.
All other git fields require the git feature (enabled by default).

Date and time specifiers

When you specify inexact date and time with = or != operator, fselect understands it as an interval.

text
fselect path from /home/user where modified = 2017-05-01

2017-05-01 means all day long from 00:00:00 to 23:59:59.

text
fselect path from /home/user where modified = '2017-05-01 15'

2017-05-01 15 means one hour from 15:00:00 to 15:59:59.

text
fselect path from /home/user where modified ne '2017-05-01 15:10'

2017-05-01 15:10 is a 1-minute interval from 15:10:00 to 15:10:59.

Other operators assume the exact date and time, which could be specified in a freer way:

text
fselect "path from /home/user where modified === 'apr 1'"
fselect "path from /home/user where modified gte 'last fri'"
fselect path from /home/user where modified gte '01/05'

Or simply use relative offsets as days:

text
fselect created, path from /home/user where created gte -2

More about writing dates in plain English

fselect uses UK locale by default, not American style dates, i.e. 08/02 means February 8th by default.

To change this behavior, supply --us-dates option to the fselect command, or put us_dates = true into the configuration file.

The safest way to specify dates is to use ISO 8601 format: YYYY-MM-DD HH:MM:SS.

Regular expressions

Rust flavor regular expressions are used.

MIME and file types

For MIME guessing use field mime. It returns a simple string with a deduced MIME type,
which is not always accurate.

text
fselect path, mime, is_binary, is_text from /home/user

is_binary and is_text return true or false based on MIME type detected.
Once again, this should not be considered as a 100% accurate result,
or even possible at all to detect a correct file type.

Other fields listed below do NOT use MIME detection.
Assumptions are being made based on file extension.

The lists below could be edited with the configuration file.

Search field Extensions
is_archive .7z, .bz2, .bzip2, .gz, .gzip, .lz, .rar, .tar, .xz, .zip
is_audio .aac, .aiff, .amr, .flac, .gsm, .m4a, .m4b, .m4p, .mp3, .ogg, .wav, .wma
is_book .azw3, .chm, .djv, .djvu, .epub, .fb2, .mobi, .pdf
is_doc .accdb, .doc, .docm, .docx, .dot, .dotm, .dotx, .mdb, .odp, .ods, .odt, .pdf, .potm, .potx, .ppt, .pptm, .pptx, .rtf, .xlm, .xls, .xlsm, .xlsx, .xlt, .xltm, .xltx, .xps
is_font .eot, .fon, .otc, .otf, .ttc, .ttf, .woff, .woff2
is_image .bmp, .exr, .gif, .heic, .jpeg, .jpg, .jxl, .png, .svg, .tga, .tiff, .webp
is_source .asm, .awk, .bas, .c, .cc, .ceylon, .clj, .coffee, .cpp, .cs, .d, .dart, .elm, .erl, .go, .groovy, .h, .hh, .hpp, .java, .jl, .js, .jsp, .jsx, .kt, .kts, .lua, .nim, .pas, .php, .pl, .pm, .py, .qml, .rb, .rs, .scala, .sol, .swift, .tcl, .ts, .vala, .vb, .zig
is_video .3gp, .avi, .flv, .m4p, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .webm, .wmv
text
fselect is_archive, path from /home/user
fselect is_audio, is_video, path from /home/user/multimedia
fselect path from /home/user where is_doc != 1
fselect path from /home/user where is_image = false
fselect path from /home/user where is_video != true

Audio support

fselect reads audio metadata via lofty, so it can search by
bitrate, sampling frequency, title, artist, album, genre, year, comment, track, and disc number across
many formats: MP3, FLAC, Ogg Vorbis, Opus, M4A/AAC/ALAC, WAV, AIFF, APE, WavPack, Musepack, and Speex.

Duration is measured in seconds.

text
fselect duration, bitrate, path from /home/user/music
fselect mp3_year, album, title from /home/user/music where artist like %Vampire% and bitrate gte 320
fselect bitrate, freq, path from /home/user/music where genre = Rap or genre = HipHop
fselect path, title, artist from /home/user/music where ext in (flac, opus, m4a)

File hashes

Column Meaning
sha1 SHA-1 digest of a file
sha2_256 or sha256 SHA2-256 digest of a file
sha2_512 or sha512 SHA2-512 digest of a file
sha3_512 or sha3 SHA3-512 digest of a file
text
fselect path, sha256, 256 from /home/user/archive limit 5
fselect path from /home/user/Download where sha1 like cb23ef45%

Output formats

text
... into FORMAT
Format Description
tabs default, columns are separated with tabulation
lines each column goes at a separate line
list columns are separated with NULL symbol, similar to -print0 argument of find
csv comma-separated columns
json array of resulting objects with requested columns
html HTML document with table
text
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
fselect path from /home/user into list | xargs -0 grep foobar

Configuration file

fselect tries to create a new configuration file if one doesn't exist.

Usual location on Linux:

text
/home/user_name/.config/fselect/config.toml

On Windows:

text
C:\Users\user_name\AppData\Roaming\jhspetersson\fselect\config.toml

Fresh config is filled with defaults, feel free to update it.

If no config on the standard paths is found, fselect checks its presence next to the executable.
You can also specify a config location with a runtime option, e.g.:

text
fselect --config /home/user_name/fselect_custom.toml name, size from /home/user_name/Music where is_audio = 1

Check for updates

fselect can be built with update-notifications feature, that enables automatic check for updates.
This check is disabled by default. To enable it, put

text
check_for_updates = true

into the config file.

Bash completion

fselect comes with a bash completion script (fselect-completion.bash) that provides tab completion for:

  • Directory paths after the from keyword
  • Output formats after the into keyword
  • Fields and functions in other contexts

To enable bash completion for fselect, you need to install the completion script. The installation method varies depending on your Linux distribution:

Ubuntu/Debian and Red Hat/Fedora/CentOS

  1. Copy the completion script to the bash completion directory:
bash
sudo cp fselect-completion.bash /etc/bash_completion.d/fselect
  1. Make the script executable:
bash
sudo chmod +x /etc/bash_completion.d/fselect
  1. Source the script or restart your shell:
bash
source /etc/bash_completion.d/fselect

Arch Linux

  1. Copy the completion script to the bash completion directory:
bash
sudo cp fselect-completion.bash /usr/share/bash-completion/completions/fselect
  1. Make the script executable:
bash
sudo chmod +x /usr/share/bash-completion/completions/fselect
  1. Source the script or restart your shell:
bash
source /usr/share/bash-completion/completions/fselect

Manual installation (any Linux distribution)

If your distribution doesn't have a standard location for bash completion scripts, or if you don't have root access, you can install the script in your home directory:

  1. Create a directory for bash completion scripts if it doesn't exist:
bash
mkdir -p ~/.bash_completion.d
  1. Copy the completion script to this directory:
bash
cp fselect-completion.bash ~/.bash_completion.d/fselect
  1. Make the script executable:
bash
chmod +x ~/.bash_completion.d/fselect
  1. Add the following line to your ~/.bashrc file:
bash
source ~/.bash_completion.d/fselect
  1. Source your ~/.bashrc file or restart your shell:
bash
source ~/.bashrc

Command-line arguments

Argument Meaning
--interactive or -i or /i Run in interactive mode
--config or -c or /config Specify config file location
--nocolor or --no-color or /nocolor Disable colors
--no-errors Suppress error reporting
--everything Use the Everything index as the file source (Windows, requires the everything build feature)
--plocate Use the plocate index as the file source (Linux, requires the plocate build feature)
--help or -h or /? or /h Show help and exit

Index-backed search (Everything / plocate)

fselect can optionally use an external file-name index as the source of candidate paths instead
of walking the filesystem. Because these indexes are prebuilt, enumerating a large directory tree is
typically much faster. Two backends are supported, each behind an opt-in build feature:

  • Everything (Windows) โ€” the voidtools Everything engine, via its
    client DLL. Enable with the everything feature and the --everything flag.
  • plocate (Linux) โ€” the plocate locate replacement, invoked as a
    subprocess. Enable with the plocate feature and the --plocate flag.
text
# Windows
cargo build --release --features everything
fselect --everything "name, size from C:\Users where size gt 100mb"

# Linux
cargo build --release --features plocate
fselect --plocate "name, size from /home where size gt 100mb"

Both backends behave the same way:

  • They can also be enabled via the configuration file (everything = true / plocate = true).
  • If the backend is unavailable โ€” Everything not running / DLL missing, or the plocate binary or
    its database missing โ€” fselect transparently falls back to normal traversal.
  • mindepth/maxdepth (and depth) constraints are applied to the index results.
  • The where/order by/select logic, functions, and all fields work exactly as with traversal โ€”
    the index only supplies the candidate paths.
  • Options that require reading the filesystem structure โ€” searching archives, or applying
    .gitignore/.hgignore/.dockerignore filters โ€” automatically use normal traversal instead.
  • Locations the index does not cover (for example, some network drives, or a stale plocate
    database) will return no results in this mode.

Interactive mode

In interactive mode, you can:

  • execute queries directly without calling fselect every time
  • use any characters without escaping them from the shell
  • run multiple searches sequentially without restarting the tool
  • edit and refine queries iteratively
  • use command history (up/down arrows) to recall previous queries
  • get current directory with pwd and change it with cd
  • suppress error reporting with errors off
  • exit with quit, exit, Ctrl+C or Ctrl+D

Environment variables

fselect respects NO_COLOR environment variable.

Exit values

Value Meaning
0 everything OK
1 I/O error has occurred during any directory listing or file reading
2 error during parsing or evaluation of the search query