fselect

Find files with SQL-like queries — filter by name, size, date, permissions, EXIF data, and more using familiar SELECT syntax.

fselect is a command-line tool for finding files using SQL-like queries. Instead of memorising find's flags or chaining ls, grep, and awk together, you write a simple SELECT statement and get back exactly the columns you asked for.

It supports filtering on dozens of attributes — file size, modification time, permissions, MIME type, image dimensions, EXIF metadata, MP3 tags, and more.

Features

  • SQL syntaxSELECT name, size FROM . WHERE size > 1gb reads exactly like what it does
  • Rich attribute set — query on size, dates, permissions, owner, MIME type, is_dir, is_symlink, and many more
  • Media metadata — filter images by width/height/EXIF tags, audio files by bitrate/artist/album
  • Output formats — results can be output as plain text, CSV, JSON, or an HTML table
  • Aggregate functionsCOUNT, SUM, MIN, MAX, AVG work just as you'd expect
  • Regex and glob matching — use LIKE, REGEXP, or glob patterns in WHERE clauses
  • No daemon — runs as a plain CLI tool, no background process required

Installation

cargo install fselect

Or via your package manager:

# Arch Linux (AUR)
paru -S fselect

# macOS
brew install fselect

# Nix
nix-env -iA nixpkgs.fselect

# Debian / Fedora
# Pre-built Linux binaries are available on the
# [releases page](https://github.com/jhspetersson/fselect/releases).

Usage

# Find all Rust source files larger than 10kb
fselect name, size FROM . WHERE name = '*.rs' AND size > 10kb

# Find recently modified files
fselect path FROM . WHERE modified > '1 day ago'

# Find the 10 largest files anywhere under /home
fselect name, size FROM /home ORDER BY size DESC LIMIT 10

# Find empty directories
fselect path FROM . WHERE is_dir = true AND size = 0

# Find images wider than 1920px (reads EXIF/image headers)
fselect name, width, height FROM ~/Pictures WHERE width > 1920

# Find MP3s by a specific artist
fselect name, artist, album FROM ~/Music WHERE artist = 'Aphex Twin'

# Output results as JSON
fselect name, size, modified FROM . WHERE name = '*.log' INTO json

# Count files by extension
fselect COUNT(*), ext FROM . GROUP BY ext ORDER BY COUNT(*) DESC

# Find world-writable files (security audit)
fselect path FROM /etc WHERE other_write = true

Supported Columns

Some of the most useful queryable attributes:

ColumnDescription
nameFilename without path
pathFull path
sizeFile size (supports kb, mb, gb suffixes)
extFile extension
created, modified, accessedTimestamps
is_dir, is_file, is_symlinkType predicates
mimeDetected MIME type
owner, groupUnix ownership
width, heightImage dimensions
artist, album, title, yearAudio metadata
exif_datetime, latitude, longitudeEXIF geotag data

Why not just use find?

find is powerful but its syntax is notoriously inconsistent — flags vary between GNU and BSD versions, combining conditions requires careful use of -and/-or, and extracting specific fields means piping into stat, awk, or xargs. fselect replaces that entire pipeline with a single, readable query.