find.flexfs
find.flexfs provides fast filesystem search by querying the metadata server directly, bypassing the FUSE layer. It supports filters on inode attributes, timestamps, size, cost, permissions, and file type.
Persistent Flags
Section titled “Persistent Flags”These flags apply to every subcommand.
| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--reportErrors | bool | false | Report errors and panics to Paradigm4 | Public |
Subcommands
Section titled “Subcommands”| Subcommand | Description | Visibility |
|---|---|---|
deinit creds | Remove the credentials for a volume | Public |
init creds | Store the credentials for a volume | Public |
license | Print license information | Public |
version | Print the build version | Public |
Search
Section titled “Search”The root command searches the volume with the filters below.
find.flexfs [flags] [path...]If no path is specified, the current directory is used. Run it from within a flexFS mount, or name an unmounted volume with --volume.
A path argument whose name matches a subcommand, such as a directory called init, is taken as the subcommand. Separate it with -- to search the directory instead:
# Runs the init subcommandfind.flexfs init
# Searches the directory named initfind.flexfs -- initOutput Control
Section titled “Output Control”| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--fields | string slice | path | Output fields (comma-separated). Use all for all fields. | Public |
--header | bool | false | Include header row in output | Public |
--limit | uint64 | 0 | Maximum number of results (0 = unlimited) | Public |
--noDecode | bool | false | Print base32-encoded paths | Public |
--outputFile, -o | string | "" | Output file path. With multiple search paths, all results go to this one file, with a single header row. | Public |
Results are written to standard output (or the --outputFile file); error messages are written to standard error. This means you can safely pipe results into other commands without error text mixing into the data.
Available fields: path, ino, mode, type, perm, blocks, size, size_bin, cost, nlink, uid, gid, ctime, mtime, atime, btime, xattrs.
The cost field is an estimated monthly storage cost in US dollars ($/month). See the analyze.flexfs cost field documentation for how it is calculated, and for what happens when the rates behind it cannot be fetched.
The xattrs field emits an inode’s extended attributes as a JSON object. See Xattrs field below.
Connection
Section titled “Connection”| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--adminAddr | string | "" | Admin server address. Only needed to override the one stored in the credentials, or alongside --token when there are none. | Internal |
--credsFile | string | ~/.flexfs/util/creds/<name> | Credentials file path | Public |
--mountPath | string | "" | Client mount path. Only needed when querying an unmounted volume whose search path passes through symbolic links with absolute targets (e.g. /mnt/flexfs/data); when run from inside a mount, this is detected automatically. | Public |
--noAdminSSL | bool | false | Disable SSL for admin server connections | Internal |
--noMetaSSL | bool | false | Disable SSL for metadata server connections | Internal |
--token | string | "" | Volume token to use, instead of reading one from a credentials file | Internal |
--volume | string | "" | Volume name, to query a volume that is not mounted here. Selects the credentials file. | Public |
Symbolic links
Section titled “Symbolic links”Search paths may pass through symbolic links. Links that stay within the volume are followed automatically, including a link as the final path component — find.flexfs /mnt/flexfs/current/logs works even when current is a link to a release directory. A link whose target points outside the volume cannot be searched and returns an error that names the link.
Inode Filters
Section titled “Inode Filters”| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--empty | bool | false | Filter for empty files or directories | Public |
--gid | uint32 | 0 | Filter by group ID | Public |
--ino | uint64 | 0 | Filter by inode number | Public |
--name | string | "" | Filter by dentry name (supports glob patterns) | Public |
--perm | string | 0 | Required permission bits (octal, with or without a leading 0 — 755 and 0755 mean the same thing; max 07777). Matches when (mode & permMask) == perm. | Public |
--permMask | string | 0777 | Bits of the file mode to test (octal, with or without a leading 0; max 07777). The default tests owner/group/other. Set to 7777 to also test setuid/setgid/sticky. | Public |
--sparse | bool | false | Filter for sparse files | Public |
--type | string | "" | Filter by inode type: b, c, d, f, l, p, s | Public |
--uid | uint32 | 0 | Filter by user ID | Public |
Size and Block Filters
Section titled “Size and Block Filters”| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--maxBlocks | uint64 | 0 | Maximum blocks filter (regular files only) | Public |
--maxCost | float64 | 0 | Maximum estimated cost filter ($/month, regular files only) | Public |
--maxNlink | uint32 | 0 | Maximum hard link count filter | Public |
--maxSize | string | 0 | Maximum byte size filter (regular files only), given as a size (10M, 1G) or bytes (1048576). | Public |
--maxSizeBin | uint32 | 0 | Maximum size bin filter (regular files only, 0-127) | Public |
--minBlocks | uint64 | 0 | Minimum blocks filter (regular files only) | Public |
--minCost | float64 | 0 | Minimum estimated cost filter ($/month, regular files only) | Public |
--minNlink | uint32 | 0 | Minimum hard link count filter | Public |
--minSize | string | 0 | Minimum byte size filter (regular files only), given as a size (10M, 1G) or bytes (1048576). | Public |
--minSizeBin | uint32 | 0 | Minimum size bin filter (regular files only, 0-127) | Public |
Timestamp Filters
Section titled “Timestamp Filters”Timestamp values are given as an RFC3339 time (2026-01-02T15:04:05Z) or seconds since epoch (Unix time).
| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--maxAtime | string | 0 | Maximum access time | Public |
--maxBtime | string | 0 | Maximum birth time | Public |
--maxCtime | string | 0 | Maximum change time | Public |
--maxMtime | string | 0 | Maximum modification time | Public |
--minAtime | string | 0 | Minimum access time | Public |
--minBtime | string | 0 | Minimum birth time | Public |
--minCtime | string | 0 | Minimum change time | Public |
--minMtime | string | 0 | Minimum modification time | Public |
Depth Control
Section titled “Depth Control”| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--maxDepth | uint32 | 0 | Maximum query depth (0 = unlimited) | Public |
--minDepth | uint32 | 0 | Minimum query depth | Public |
Examples
Section titled “Examples”File discovery
Section titled “File discovery”Find all files larger than 1 GiB:
find.flexfs --minSize 1G --type f /mnt/flexfsFind files by name pattern with full metadata:
find.flexfs --name "*.bam" --fields all --header /mnt/flexfs/dataFind empty directories (candidates for cleanup):
find.flexfs --type d --empty /mnt/flexfsFind all symlinks under a path:
find.flexfs --type l --fields path,size /mnt/flexfs/dataCost and storage analysis
Section titled “Cost and storage analysis”Find the most expensive files (costing more than $1/month):
find.flexfs --minCost 1 --type f --fields path,size,cost --header /mnt/flexfsFind cold files (not accessed in over 6 months, size bin 6+) that are still large:
find.flexfs --minSizeBin 6 --minSize 1G --type f \ --fields path,size,size_bin,cost --header /mnt/flexfsTimestamp queries
Section titled “Timestamp queries”Find files not accessed since January 1 2025 (stale data candidates):
find.flexfs --maxAtime 2025-01-01T00:00:00Z --type f /mnt/flexfsFind files modified in a specific window (e.g. during an incident):
find.flexfs --minMtime 2025-03-15T00:00:00Z --maxMtime 2025-03-16T00:00:00Z --type f \ --fields path,size,mtime --header /mnt/flexfsFind files created in the last 7 days:
# --minBtime accepts either an RFC3339 time or seconds since epoch:find.flexfs --minBtime "$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)" --type f /mnt/flexfsfind.flexfs --minBtime "$(date -d '7 days ago' +%s)" --type f /mnt/flexfsPermissions audit
Section titled “Permissions audit”Find files with exact permissions rwxrwxrwx:
find.flexfs --perm 777 --type f --fields path,perm /mnt/flexfsFind world-writable files (other-write bit set):
find.flexfs --perm 2 --permMask 2 --type f --fields path,perm /mnt/flexfsFind files with the setuid bit set:
find.flexfs --perm 4000 --permMask 4000 --type f --fields path,perm /mnt/flexfsOwnership
Section titled “Ownership”Find all files owned by a specific user:
find.flexfs --uid 1001 --type f --fields path,size,uid /mnt/flexfsSparse files
Section titled “Sparse files”Find sparse files (logical size exceeds allocated blocks):
find.flexfs --sparse --type f --fields path,size,blocks /mnt/flexfsExporting and direct connection
Section titled “Exporting and direct connection”Export a full file inventory to TSV:
find.flexfs --fields all --header --type f \ --outputFile /tmp/inventory.tsv /mnt/flexfsQuery a volume directly without a local mount:
find.flexfs --volume <volume-name> --type d /Output Format
Section titled “Output Format”Output is tab-separated. The columns correspond to the --fields list. When --header is set, the first line contains field names.
Xattrs field
Section titled “Xattrs field”The xattrs field emits all of an inode’s extended attributes as a single JSON object, occupying one tab-separated column:
{"user.department":"cmVzZWFyY2g=","user.project":"Z2Vub21pY3M="}- Keys are attribute names, including the namespace prefix, exactly as stored. Names settable with
setfattrlive in theuser.,trusted., andsecurity.namespaces;system.andflexfs.also appear, holding attributes flexFS maintains on your behalf (see below). - Values are base64-encoded (standard alphabet, with padding). Extended attribute values are arbitrary binary data, so they are never emitted raw. Decode with
base64 -d; in the example above the values are the stringsresearchandgenomics. - Keys are sorted lexicographically, so the object is byte-for-byte stable across runs for a given inode.
- An inode with no extended attributes emits
{}, not an empty column. - The object is always one line and always tab-free: base64 values cannot contain a tab or newline, and JSON escapes both characters if an attribute name contains them. An
xattrscolumn therefore never breaks the tab-separated row structure. - There are no filter flags for extended attributes.
xattrsis an output field only — filter the results downstream (see the examples below).
Which attributes appear
Section titled “Which attributes appear”Everything stored on the inode appears, including attributes flexFS maintains itself. Beyond whatever your applications set under user., expect to see:
| Attribute | Written by | Contents |
|---|---|---|
system.posix_acl_access | ACLs (--acl) | Packed POSIX ACL structure for the inode’s access ACL |
system.posix_acl_default | ACLs (--acl) | Packed POSIX ACL structure inherited by new children of a directory |
security.capability | setcap | File capability set. Stripped automatically on write, so it may disappear between runs. |
flexfs.iflags | chattr | The immutable and append-only inode flags set with chattr. Present even on volumes mounted without --xattr, and removed entirely once every flag is cleared. |
Setting and reading extended attributes through a mount requires --xattr, but that option gates the FUSE layer only. find.flexfs queries the metadata server, so it reports stored attributes regardless of how any mount is currently configured — including attributes written earlier on a volume now mounted without --xattr.
Encrypted volumes
Section titled “Encrypted volumes”find.flexfs queries the metadata server directly and reads the stored form of each attribute. On a volume using metadata encryption, encryption and decryption happen only in the mount client, so attribute names and values reach find.flexfs as ciphertext:
{"5LJ0aBv...=":"n4Kc2Rv1Zt8..."}The name is base64 of the AES-256-GCM ciphertext of the name; the value is base64 of the AES-256-GCM ciphertext of the value. Neither is recoverable from find.flexfs output. Reading extended attributes in plaintext on an encrypted volume requires going through a mount — getfattr on the mounted path. Note that --noDecode is unrelated: it governs base32 path encoding only and has no effect on the xattrs column.
Querying extended attributes
Section titled “Querying extended attributes”List every file that carries any extended attribute:
find.flexfs --type f --fields path,xattrs /mnt/flexfs | awk -F'\t' '$2 != "{}"'Report a specific attribute in plaintext, one file per line:
find.flexfs --type f --fields path,xattrs /mnt/flexfs \ | jq -Rr 'split("\t") | (.[1] | fromjson)["user.project"] as $v | select($v != null) | .[0] + "\t" + ($v | @base64d)'Find files carrying a POSIX ACL:
find.flexfs --type f --fields path,perm,xattrs /mnt/flexfs \ | grep 'system.posix_acl_access'init creds
Section titled “init creds”Store the volume token find.flexfs uses for a volume.
find.flexfs init creds --adminAddr <admin-host:port> [flags]The token is prompted for unless --token is given. The volume’s name is taken from the admin server, so the credentials are always filed under the name a mount reports, and the token is checked for the admin flag before anything is written.
| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--adminAddr | string | "" | Admin server address (required) | Public |
--credsFile | string | ~/.flexfs/util/creds/<name> | Credentials file path | Public |
--force | bool | false | Overwrite existing credentials file | Public |
--noAdminSSL | bool | false | Disable SSL for admin server connections | Internal |
--token | string | "" | Volume token (prompted for if omitted) | Public |
--volume | string | "" | Volume name, checked against the token | Public |
init on its own does the same thing as init creds.
Credentials
Section titled “Credentials”find.flexfs queries the metadata server, which requires a volume token carrying the admin flag. Store one per volume:
find.flexfs init creds --adminAddr admin.example.com:443The command prompts for the token, confirms with the admin server that it allows reporting queries, and files it under the volume’s name. See Volume Tokens for how to obtain one.
Credentials are looked for in this order:
~/.flexfs/util/creds/<volume-name>, written byfind.flexfs init creds.~/.flexfs/mount/creds/<volume-name>, written bymount.flexfs init credsfor the same user.
analyze.flexfs, dedup.flexfs and find.flexfs share the first of these, so one init creds serves all three — and one deinit creds removes the credentials all three were using.
Both files must be readable only by their owner (chmod 600); a file readable by others is refused.
--credsFile moves the first of these. Give the same value to init creds and to the query, or credentials will be written somewhere the query does not look — and to the other two utilities as well, if they are to go on sharing one file.
Each user needs their own credentials. A mount created by root keeps its credentials under /root, which other users cannot read, so give each person who runs reporting queries a token of their own.
Tokens scoped to a subdirectory
Section titled “Tokens scoped to a subdirectory”A volume token can be issued for one subdirectory of a volume rather than the whole of it (see Volume Tokens). Every query made with such a token is answered from that subdirectory, whichever part of the volume the mount itself shows.
find.flexfs accounts for the difference, so paths are always given the way they look on this machine. With a volume mounted whole at /flexfs-1 and a token scoped to /sub-1:
find.flexfs /flexfs-1/sub-1 # the token's whole subtreefind.flexfs /flexfs-1/sub-1/data # part of itfind.flexfs /flexfs-1 # refused: outside the token's subtreeThe first of those is the same query as find.flexfs --volume <name> /, which names the path as the token sees it because no mount is involved to interpret it against.
To make the adjustment, find.flexfs asks the admin server what the token is scoped to — once per volume, on every run. Nothing about the token is cached on disk, so a token that is reissued or re-scoped needs no re-initialization, and a token passed with --token is treated exactly like a stored one. The admin server must therefore be reachable for a query made inside a mount.
deinit creds
Section titled “deinit creds”Remove the credentials for a volume.
find.flexfs deinit creds <volume-name>Removing credentials that are not there succeeds, so this is safe to run twice.
| Flag | Type | Default | Description | Visibility |
|---|---|---|---|---|
--credsFile | string | ~/.flexfs/util/creds/<name> | Credentials file path | Public |