fselect

March 27, 2026 · View on GitHub

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 for IN and EXISTS
Date and time specifiers
Regular expressions
MIME and file types
MP3 support
File hashes
Output formats
Configuration file
Bash completion
Command-line arguments
Interactive mode
Environment variables
Exit values

Basic usage

fselect [ARGS] COLUMN[, COLUMN...] [from ROOT[, ROOT...]] [where EXPR] [group by COLUMNS] [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.

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.

Columns and fields

ColumnMeaningComment
nameReturns the name (with extension) of the file
filename or fnameReturns the file name without extension
extension or extReturns the extension of the file
pathReturns the relative path of the file
abspathReturns the absolute path of the file
directory or dirname or dirReturns the directory of the file
absdirReturns the absolute directory of the file
sizeReturns the size of the file in bytes
fsize or hsizeReturns the size of the file accompanied with the unit
uidReturns the UID of the owner
gidReturns the GID of the owner's group
accessedReturns the time the file was last accessed (YYYY-MM-DD HH:MM:SS)
createdReturns the file creation date (YYYY-MM-DD HH:MM:SS)Windows, macOS, and Linux (kernel 4.11+ with ext4/btrfs/XFS)
modifiedReturns the time the file was last modified (YYYY-MM-DD HH:MM:SS)
atimeReturns the last access time as a Unix timestamp (seconds since epoch)Available only on Unix
mtimeReturns the last modification time as a Unix timestamp (seconds since epoch)Available only on Unix
ctimeReturns the last status change time as a Unix timestamp (seconds since epoch)Available only on Unix
is_dirReturns a boolean signifying whether the file path is a directory
is_fileReturns a boolean signifying whether the file path is a file
is_symlinkReturns a boolean signifying whether the file path is a symlink
is_pipe or is_fifoReturns a boolean signifying whether the file path is a FIFO or pipe file
is_char or is_characterReturns a boolean signifying whether the file path is a character device or character special file
is_blockReturns a boolean signifying whether the file path is a block or block special file
is_socketReturns a boolean signifying whether the file path is a socket file
is_hiddenReturns a boolean signifying whether the file is a hidden file (e.g., files that start with a dot on *nix)
has_xattrsReturns a boolean signifying whether the file has extended attributes or alternate data streams on Windows
xattr_countReturns the count of extended attributes on the file or alternate data streams on Windows
extattrsReturns the extended file attributes as a string of chattr/lsattr flag lettersAvailable only on Linux
has_extattrsReturns a boolean signifying whether the file has any extended file attributes setAvailable only on Linux
aclReturns all ACL entries in standard form (POSIX on Linux, DACL on Windows)Available only on Linux and Windows
has_aclReturns a boolean signifying whether the file has POSIX ACL entries beyond standard Unix permissions or Windows explicit ACEsAvailable only on Linux and Windows
default_aclReturns all default POSIX ACL entries in standard formAvailable only on Linux
has_default_aclReturns a boolean signifying whether the directory has default POSIX ACL entriesAvailable only on Linux
has_capabilities or has_capsReturns a boolean signifying whether the file has capabilitiesAvailable only on Linux
capabilities or capsReturns a string describing Linux capabilities assigned to a fileAvailable only on Linux
deviceReturns the code of device the file is stored onAvailable only on Unix
rdevReturns the device ID for special files (character and block devices)Available only on Unix
inodeReturns the number of inodeAvailable only on Linux
blocksReturns the number of blocks (256 bytes) the file occupiesAvailable only on Linux
hardlinksReturns the number of hardlinks of the fileAvailable only on Linux
modeReturns the permissions of the owner, group, and everybody (similar to the first field in ls -la)
userReturns the name of the owner for this fileAvailable only on *nix platforms with users feature enabled
user_readReturns a boolean signifying whether the file can be read by the owner
user_writeReturns a boolean signifying whether the file can be written by the owner
user_execReturns a boolean signifying whether the file can be executed by the owner
user_allReturns a boolean signifying whether the file can be fully accessed by the owner
groupReturns the name of the owner's group for this fileAvailable only on *nix platforms with users feature enabled
group_readReturns a boolean signifying whether the file can be read by the owner's group
group_writeReturns a boolean signifying whether the file can be written by the owner's group
group_execReturns a boolean signifying whether the file can be executed by the owner's group
group_allReturns a boolean signifying whether the file can be fully accessed by the group
other_readReturns a boolean signifying whether the file can be read by others
other_writeReturns a boolean signifying whether the file can be written by others
other_execReturns a boolean signifying whether the file can be executed by others
other_allReturns a boolean signifying whether the file can be fully accessed by the others
suid or is_suidReturns a boolean signifying whether the file permissions have a SUID bit set
sgid or is_sgidReturns a boolean signifying whether the file permissions have a SGID bit set
sticky or is_stickyReturns a boolean signifying whether the file permissions have a sticky bit set
widthReturns the number of pixels along the width of the photo or MP4 file
heightReturns the number of pixels along the height of the photo or MP4 file
mimeReturns MIME type of the file
is_binaryReturns a boolean signifying whether the file has binary contents
is_textReturns a boolean signifying whether the file has text contents
line_countReturns a number of lines in a text file
exif_datetimeReturns date and time of taken photo
exif_datetime_original or exif_dtoReturns original date and time when the photo was taken
exif_altitude or exif_altReturns GPS altitude of taken photo
exif_latitude or exif_latReturns GPS latitude of taken photo
exif_longitude or exif_lng or exif_lonReturns GPS longitude of taken photo
exif_makeReturns name of the camera manufacturer
exif_modelReturns camera model
exif_softwareReturns software name with which the photo was taken
exif_versionReturns the version of EXIF metadata
exif_exposure_time or exif_exptimeReturns exposure time of the photo taken
exif_apertureReturns aperture value of the photo taken
exif_shutter_speedReturns shutter speed of the photo taken
exif_f_number or exif_f_numReturns F-number of the photo taken
exif_iso_speed or exif_isoReturns ISO speed of the photo taken (EXIF 2.3 ISOSpeed tag)
exif_sensitivity or exif_photo_sensitivityReturns photographic sensitivity (ISO) of the photo taken
exif_focal_length or exif_focal_lenReturns focal length of the photo taken
exif_lens_makeReturns lens manufacturer used to take the photo
exif_lens_modelReturns lens model used to take the photo
exif_description or exif_descReturns image description from EXIF metadata
exif_artistReturns the artist or photographer name
exif_copyrightReturns the copyright information
exif_orientationReturns the image orientation
exif_flashReturns the flash status when the photo was taken
exif_color_spaceReturns the color space of the image
exif_exposure_program or exif_exp_programReturns the exposure program used
exif_exposure_bias or exif_exp_biasReturns the exposure bias value
exif_white_balance or exif_wbReturns the white balance mode
exif_metering_modeReturns the metering mode
exif_scene_type or exif_sceneReturns the scene capture type
exif_contrastReturns the contrast setting
exif_saturationReturns the saturation setting
exif_sharpnessReturns the sharpness setting
exif_body_serial or exif_serialReturns the camera body serial number
exif_lens_serialReturns the lens serial number
exif_user_comment or exif_commentReturns the user comment from EXIF metadata
exif_image_width or exif_widthReturns the image width from EXIF metadata
exif_image_height or exif_heightReturns the image height from EXIF metadata
exif_max_apertureReturns the max aperture value of the lens
exif_digital_zoom or exif_dzoomReturns the digital zoom ratio
mp3_title or titleReturns the title of the audio file taken from the file's metadata
mp3_album or albumReturns the album name of the audio file taken from the file's metadata
mp3_artist or artistReturns the artist of the audio file taken from the file's metadata
mp3_genre or genreReturns the genre of the audio file taken from the file's metadata
mp3_yearReturns the year of the audio file taken from the file's metadata
mp3_freq or freqReturns the sampling rate of audio or video file
mp3_bitrate or bitrateReturns the bitrate of the audio file in kbps
durationReturns the duration of audio file in seconds
is_shebangReturns a boolean signifying whether the file starts with a shebang (#!)
is_emptyReturns a boolean signifying whether the file is empty or the directory is empty
is_archiveReturns a boolean signifying whether the file is an archival filedefault extensions
is_audioReturns a boolean signifying whether the file is an audio filedefault extensions
is_bookReturns a boolean signifying whether the file is a bookdefault extensions
is_docReturns a boolean signifying whether the file is a documentdefault extensions
is_fontReturns a boolean signifying whether the file is a fontdefault extensions
is_imageReturns a boolean signifying whether the file is an imagedefault extensions
is_sourceReturns a boolean signifying whether the file is source codedefault extensions
is_videoReturns a boolean signifying whether the file is a video filedefault extensions
sha1Returns SHA-1 digest of a file
sha2_256 or sha256Returns SHA2-256 digest of a file
sha2_512 or sha512Returns SHA2-512 digest of a file
sha3_512 or sha3Returns SHA-3 digest of a file

File naming terminology

Let's see how all these are different:

fselect abspath, absdir, path, dir, name, filename, ext from /home/user/projects where is_file
ColumnValueComment
abspath/home/user/projects/foobar/content/readme.mdAbsolute path includes everything
absdir/home/user/projects/foobar/contentAbsolute directory includes everything except the last segment
pathfoobar/content/readme.mdPath is relative to the search root /home/user/projects
dirfoobar/contentRelative directory
namereadme.mdname = filename + ext
filenamereadme
extmd

File Naming Terminology

Functions

Aggregate functions

Queries using these functions return only one result row.

FunctionMeaningExample
AVGAverage of all valuesselect avg(size) from /home/user/Downloads
COUNTNumber of all valuesselect count(*) from /home/user/Downloads
MAXMaximum valueselect max(size) from /home/user/Downloads
MINMinimum valueselect min(size) from /home/user where size gt 0
SUMSum of all valuesselect sum(size) from /home/user/Downloads
STDDEV_POP, STDDEV or STDPopulation standard deviation, the square root of varianceselect stddev_pop(size) from /home/user/Downloads
STDDEV_SAMPSample standard deviation, the square root of sample varianceselect stddev_samp(size) from /home/user/Downloads
VAR_POP or VARIANCEPopulation varianceselect var_pop(size) from /home/user/Downloads
VAR_SAMPSample varianceselect var_samp(size) from /home/user/Downloads

Date functions

Used mostly for formatting results.

FunctionMeaningExample
CURRENT_DATE or CUR_DATE or CURDATEReturns current dateselect modified, path where modified = CURDATE()
CURRENT_TIME or CUR_TIME or CURTIMEReturns current local time (HH:MM:SS)select CURRENT_TIME()
CURRENT_TIMESTAMP or NOWReturns current local timestamp (YYYY-MM-DD HH:MM:SS)select NOW()
DAYExtract day of the monthselect day(modified) from /home/user/Downloads
MONTHExtract month of the yearselect month(name) from /home/user/Downloads
YEARExtract year of the dateselect year(name) from /home/user/Downloads
DOW or DAYOFWEEKReturns day of the week (1 - Sunday, 2 - Monday, etc.)select name, modified, dow(modified) from /home/user/projects/FizzBuzz
DAYNAMEReturns the name of the day of the weekselect dayname(modified) from /home/user/Downloads
DOY or DAYOFYEARReturns the day of the year (1-366)select dayofyear(modified) from /home/user/Downloads
DATE_ADD or DATEADDAdd days to a dateselect "date_add(modified, 30) from /home/user"
DATE_SUB or DATESUBSubtract days from a dateselect "date_sub(modified, 7) from /home/user"
DATE_DIFF or DATEDIFFNumber of days between two datesselect "date_diff(modified, created) from /home/user"
FROM_UNIXTIMEConvert a Unix timestamp to a datetime stringselect "from_unixtime(mtime) from /home/user"
LAST_DAY or LAST_DATELast day of the month for a given dateselect "last_day(modified) from /home/user"

User functions

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

FunctionMeaningExample
CURRENT_UIDCurrent real UIDselect CURRENT_UID()
CURRENT_USERCurrent real UID's nameselect CURRENT_USER()
CURRENT_GIDCurrent primary GIDselect CURRENT_GID()
CURRENT_GROUPCurrent primary GID's nameselect 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.

FunctionMeaningExample
HAS_XATTRCheck if xattr existsselect "name, has_xattr(user.test) from /home/user"
XATTRGet value of xattrselect "name, xattr(user.test) from /home/user"
HAS_EXTATTRCheck if a specific extended file attribute flag is set (Linux only)select "name from / where has_extattr('i')"
HAS_ACL_ENTRYCheck if a specific POSIX ACL entry exists (Linux only)select "name from /data where has_acl_entry('user:john')"
ACL_ENTRYGet permissions of a specific POSIX ACL entry (Linux only)select "name, acl_entry('group:staff') from /data"
HAS_DEFAULT_ACL_ENTRYCheck if a specific default POSIX ACL entry exists (Linux only)select "name from /data where has_default_acl_entry('user:john')"
DEFAULT_ACL_ENTRYGet permissions of a specific default POSIX ACL entry (Linux only)select "name, default_acl_entry('group:staff') from /data"
HAS_CAPABILITY or HAS_CAPCheck if given Linux capability exists for the fileselect "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:

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

fselect name from C:\ where has_acl = true
fselect "name, acl from C:\Users where has_acl = true"

Extended file attributes

fselect can read and query extended file attributes (also known as file flags) that are managed with chattr and displayed with lsattr. This feature is available only on Linux and works on ext2/ext3/ext4, btrfs, and other filesystems that support the FS_IOC_GETFLAGS ioctl.

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

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

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 /data where has_extattr('a')"

String functions

Used mostly for formatting results.

FunctionMeaningExample
LENGTH or LENLength of string valueselect length(name) from /home/user/Downloads order by 1 desc limit 10
LOWER or LOWERCASE or LCASEConvert value to lowercaseselect lower(name) from /home/user/Downloads
UPPER or UPPERCASE or UCASEConvert value to uppercaseselect upper(name) from /home/user/Downloads
INITCAPReturns first letter of each word uppercase, all other letters lowercaseselect initcap('MICHAEL SMITH')
TO_BASE64 or BASE64Encode value to Base64select base64(name) from /home/user/Downloads
FROM_BASE64Decode value from Base64select from_base64('ZnNlbGVjdCByb2Nrcw==')
CONCATReturns concatenated string of expression valuesselect CONCAT('Name is ', name, ' size is ', fsize, '!!!') from /home/user/Downloads
CONCAT_WSReturns concatenated string of expression values with specified delimiterselect 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 toselect replace(name, metallica, MetaLLicA) from /home/user/Music/Rock
TRIMReturns string with whitespaces at the beginning and the end strippedselect trim(title), trim(artist), trim(album) from /home/user/Music into json
LTRIMReturns string with whitespaces at the beginning strippedselect ltrim(title) from /home/user/Music into json
RTRIMReturns string with whitespaces at the end strippedselect rtrim(title) from /home/user/Music into json

Japanese string functions

Used for detecting Japanese symbols in file names and such.

FunctionMeaningExample
CONTAINS_JAPANESE or JAPANESECheck if string value contains Japanese symbolsselect japanese(name) from /home/user/Downloads
CONTAINS_KANA or KANACheck if string value contains kana symbolsselect kana(name) from /home/user/Downloads
CONTAINS_HIRAGANA or HIRAGANACheck if string value contains hiragana symbolsselect contains_hiragana(name) from /home/user/Downloads
CONTAINS_KATAKANA or KATAKANACheck if string value contains katakana symbolsselect katakana(name) from /home/user/Downloads
CONTAINS_KANJI or KANJICheck if string value contains kanji symbolsselect kanji(name) from /home/user/Downloads

Greek string functions

Used for detecting Greek symbols in file names and such.

FunctionMeaningExample
CONTAINS_GREEK or GREEKCheck if string value contains Greek symbolsselect greek(name) from /home/user/Downloads

Other functions

FunctionMeaningExample
BINConvert integer value to binary representationselect name, size, bin(size) from /home/user/Downloads
HEXConvert integer value to hexadecimal representationselect name, size, hex(size), upper(hex(size)) from /home/user/Downloads
OCTConvert integer value to octal representationselect name, size, oct(size) from /home/user/Downloads
ABSReturns absolute value of the expressionselect abs(-5)
POWER or POWRaise the value to the specified powerselect pow(2, 3)
SQRTReturns square root of the valueselect sqrt(25)
LOGReturns logarithm of the valueselect log(1000)
LNReturns natural logarithm of the valueselect ln(10)
EXPReturns Euler's number raised to the power of the valueselect exp(2)
LEASTReturns the smallest of the expression valuesselect least(1, 2, 3)
GREATESTReturns the largest of the expression valuesselect greatest(1, 2, 3)
PIReturns pi (π) constantselect pi()
FLOORReturns the largest integer less than or equal to the valueselect floor(2.5)
CEIL or CEILINGReturns the smallest integer greater than or equal to the valueselect ceil(2.5)
ROUNDReturns the value rounded to the nearest integer, or to a given number of decimal placesselect round(2.5) or select round(pi(), 2)
CONTAINStrue if file contains string, false if notselect contains(TODO) from /home/user/Projects/foo/src
COALESCEReturns first nonempty expression valueselect name, size, COALESCE(sha256, '---') from /home/user/Downloads
RANDOM or RANDReturns 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_TIMEReturns human-readable durations of time in seconds like 2min 26sselect format_time(duration) from /home/user/Music
FORMAT_SIZEReturns formatted size of a fileselect name, FORMAT_SIZE(size, '%.0') from /home/user/Downloads order by size desc limit 10

Let's try FORMAT_SIZE with different format specifiers:

SpecifierMeaningOutput
format_size(1678123)Default output1.60MiB
format_size(1678123, ' ')Put a space before units1.60 MiB
format_size(1678123, '%.0')Round up decimal part2MiB
format_size(1678123, '%.1')One place for decimal part1.6MiB
format_size(1678123, '%.2')Two places for decimal part1.60MiB
format_size(1678123, '%.2 ')Two places for decimal part, and put a space before units1.60 MiB
format_size(1678123, '%.2 d')Use decimal divider, e.g. 1000-based units, not 1024-based1.68 MB
format_size(1678123, '%.2 c')Use conventional format, e.g. 1024-based divider, but display 1000-based units1.60 MB
format_size(1678123, '%.2 k')Display file size in specified unit, this time in kibibytes1638.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 kilobyte1678 KB
format_size(1678123, '%.0kb')Don't put a space1678KB
format_size(1678123, '%.0s')Use short units2M
format_size(1678123, '%.0 s')Use short units with a space2 M

File size units

SpecifierMeaningBytes
t or tibtebibyte1024 * 1024 * 1024 * 1024
tbterabyte1000 * 1000 * 1000 * 1000
g or gibgibibyte1024 * 1024 * 1024
gbgigabyte1000 * 1000 * 1000
m or mibmebibyte1024 * 1024
mbmegabyte1000 * 1000
k or kibkibibyte1024
kbkilobyte1000
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

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

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

OptionMeaning
mindepth NMinimum search depth. Default is unlimited. Depth 1 means skip one directory level and search further.
maxdepth NMaximum 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.
symlinksIf specified, search process will follow symlinks. Default is not to follow. Synonym is sym.
archivesSearch within archives. Only zip archives are supported. Default is not to include archived content into the search results. Synonym is arc.
gitignoreSearch respects .gitignore files found. Synonym is git.
hgignoreSearch respects .hgignore files found. Synonym is hg.
dockerignoreSearch respects .dockerignore files found. Synonym is dock.
nogitignoreDisable .gitignore parsing during the search. Synonym is nogit.
nohgignoreDisable .hgignore parsing during the search. Synonym is nohg.
nodockerignoreDisable .dockerignore parsing during the search. Synonym is nodock.
dfsDepth-first search mode.
bfsBreadth-first search mode. This is the default.
regexpUse 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

OperatorAlias
+plus
-minus
*mul
/div
%mod

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

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:

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

Example: Find files with multiple levels of correlation:

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:

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

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:

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:

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:

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:

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

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:

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:

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:

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.

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.

Date and time specifiers

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

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.

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.

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:

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:

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.

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 fieldExtensions
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, .rb, .rs, .scala, .sol, .swift, .tcl, .ts, .vala, .vb, .zig
is_video.3gp, .avi, .flv, .m4p, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .webm, .wmv
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

MP3 support

fselect can parse basic MP3 metadata and search by bitrate or sampling frequency of the first frame, title of the track, artist's name, album, genre, and year.

Duration is measured in seconds.

List of supported genres

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

File hashes

ColumnMeaning
sha1SHA-1 digest of a file
sha2_256 or sha256SHA2-256 digest of a file
sha2_512 or sha512SHA2-512 digest of a file
sha3_512 or sha3SHA3-512 digest of a file
fselect path, sha256, 256 from /home/user/archive limit 5
fselect path from /home/user/Download where sha1 like cb23ef45% 

Output formats

... into FORMAT
FormatDescription
tabsdefault, columns are separated with tabulation
lineseach column goes at a separate line
listcolumns are separated with NULL symbol, similar to -print0 argument of find
csvcomma-separated columns
jsonarray of resulting objects with requested columns
htmlHTML document with table
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:

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

On Windows:

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

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

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:
sudo cp fselect-completion.bash /etc/bash_completion.d/fselect
  1. Make the script executable:
sudo chmod +x /etc/bash_completion.d/fselect
  1. Source the script or restart your shell:
source /etc/bash_completion.d/fselect

Arch Linux

  1. Copy the completion script to the bash completion directory:
sudo cp fselect-completion.bash /usr/share/bash-completion/completions/fselect
  1. Make the script executable:
sudo chmod +x /usr/share/bash-completion/completions/fselect
  1. Source the script or restart your shell:
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:
mkdir -p ~/.bash_completion.d
  1. Copy the completion script to this directory:
cp fselect-completion.bash ~/.bash_completion.d/fselect
  1. Make the script executable:
chmod +x ~/.bash_completion.d/fselect
  1. Add the following line to your ~/.bashrc file:
source ~/.bash_completion.d/fselect
  1. Source your ~/.bashrc file or restart your shell:
source ~/.bashrc

Command-line arguments

ArgumentMeaning
--interactive or -i or /iRun in interactive mode
--config or -c or /configSpecify config file location
--nocolor or --no-color or /nocolorDisable colors
--no-errorsSuppress error reporting
--help or -h or /? or /hShow help and exit

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

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