Pseek
Fast and powerful command-line search tool for finding files, directories, and text content.
Table of Contents
- Features
- Installation
- Basic Usage
- Command Options Table
- Specifying the Root Directory
- Search Types
- Query Modes
- Expression Queries
- Automatic Filtering
- Manual Filtering
- Parallel Search
- Archive Search
- Archive Filters
- What's RAR Backend, and How to Configure It
- Output Options
- Requirements
Features
- Search file names
- Search directory names
- Search file contents
- Boolean query expressions (
and,or,not) - Regular expressions
- Fuzzy matching
- Whole-word matching
- Case-sensitive search
- Search inside archive files
- Archive recursion depth control
- Extension filters
- Path filters
- Size filtering
- Depth filtering
- Automatic filtering (Supports git rules)
- Parallel search
- Highlight matches in output
- Cross-platform (Linux, macOS, Windows)
Installation
Note: Pseek includes a native Rust extension. Currently, pre-built wheels are provided for Linux only. If you are installing Pseek on another platform, Rust and Cargo must be installed so the extension can be built locally.
Install from PyPI (Recommended)
python -m pip install pseek
Install from Source
git clone https://github.com/grootle/pseek.git
cd pseek
Installation via pip
python -m venv venv
# Activate the virtual environment, then install Pseek
python -m pip install .
Alternatively, if you use uv:
uv sync
uv run psk --help
Basic Usage
psk <query> <path> [options]
Example:
psk error
If no search type is specified, Pseek searches:
- File names
- Directory names
- File contents
simultaneously.
To search for a query that starts with -, use -- to mark the end of options:
psk -- --path # The query is "--path"
Of course the search query is optional. When no query is provided, Pseek displays the files and directories and file contents within the selected scope.
All other filters still apply, including --glob, --depth, --size, ignore rules, and other filtering options.
This makes Pseek useful as a flexible alternative to ls or cat, allowing you to inspect a filtered view of a directory tree and file contents.
# List files and directories and file contents
psk
# List only Python files
psk --ext py
# List everything up to depth 2
psk --depth :2
# List everything except the build directory
psk --exclude build
Command Options
| Option | Description |
|---|---|
--file |
Search only in file names |
--directory |
Search only in directory names |
--content |
Search within file contents |
--ext, --exclude-ext |
Filter by file extension (e.g., txt, log) |
--case-sensitive |
Make the search case-sensitive (except when --expr is enabled, in which case you can make it case sensitive by putting c before term: c"foo") |
--regex |
Use regular expressions to search (except when --expr is enabled, in which case you can make it regex by putting r before term: r"foo") |
--include, --exclude |
Limit search results to specific set of directories or files |
--re-include, --re-exclude |
Limit search results to specific directories or files with regex |
--word |
Match the whole word only (except when --expr is enabled, in which case you can make it match whole word by putting w before term: w"foo") |
--expr |
Enable boolean query expressions. Example: r"foo.*bar" and ("bar" or "baz") and not "qux". Prefixes: r=regex, c=case-sensitive, w=whole-word, f=fuzzy |
--context |
Show N context lines before and after matches, or use N:M to specify before:after |
--full-path |
By default, query is only matched against the filename or directory name (this applies only when searching for files or directories, not file contents). Using this flag, query is matched against the full path (and, if --absolute-path flag is enabled, against the absolute path) |
--depth |
Limit directory traversal to given depth range. By default, there is no limit on search depth |
--timeout |
Stop the search after the specified number of seconds |
--fuzzy |
Enable fuzzy search (Highlighting and counting matches are disabled in this mode if --word is not enabled to prevent the program from slowing down). except when --expr is enabled, in which case you can make it fuzzy by putting f before term: f"foo" |
--fuzzy-level |
Fuzzy matching threshold (0-99). Higher values require closer matches (default: 80) |
--size |
Limit results based on the size of files |
--unrestricted |
Disable all automatic filters except the binary file filter for content search |
--no-ignore |
It disables all automatic filters related to git. This implies include --no-git-ignore, --no-ignore-dot, --no-ignore-exclude, --no-ignore-global, --no-ignore-parent |
--no-git-ignore |
Don't respect filter rules from .gitignore files |
--no-ignore-dot |
Don't respect filter rules from .ignore files |
--no-ignore-exclude |
Don't respect filter rules from files that are manually configured for the repository. For example, this includes git's .git/info/exclude |
--no-ignore-global |
Don't respect filter rules from ignore files that come from global sources such as git's core.excludesFile configuration option (which defaults to $HOME/.config/git/ignore) |
--no-ignore-parent |
When this flag is set, filter rules from ignore files found in parent directories are not respected. By default, Pseek will ascend the parent directories of the current working directory to look for any applicable ignore files that should be applied |
--no-require-git |
When this flag is given, source control ignore files such as .gitignore are respected even if no git repository is present. By default, Pseek will only respect filter rules from source control ignore files when Pseek detects that the search is executed inside a source control repository. For example, when a .git directory is observed |
--hidden |
Search hidden files and directories. By default, hidden files and directories are skipped. Note that if a hidden file or a directory is whitelisted in an ignore file, then it will be searched even if this flag isn't provided. Similarly if a hidden file or directory is given explicitly as path argument or include option |
--follow |
Follow symbolic links while traversing directories. This behavior is disabled by default. Symbolic link loops and broken links are automatically skipped. Symbolic links are given explicitly as path argument or include option then they will be searched even if this flag is disabled |
--glob |
Include or exclude files and directories for searching that match the given glob. This always overrides any other ignore logic. Multiple glob flags may be used. Globbing rules match .gitignore globs |
--archive |
Enable search within archive files (e.g. zip, rar, 7z, gz, bz2, xz, tar, tar.gz, tar.bz2, tar.xz) |
--arc-depth |
Limit nested archive to given depth range. By default, there is no limit |
--arc-ext, --arc-exc-ext |
Filter by file extension inside archive files |
--arc-include, --arc-exclude |
Limit search results to specific set of directories or files inside archive files |
--arc-size |
Limit results based on the size of files in the archive |
--rar-backend |
Path to RAR backend tool (e.g. UnRAR.exe, ...) |
--absolute-path |
Display full path of files and directories |
--paths-only |
Only show matching file paths for content search |
--stats |
Show search statistics including result counts and search time |
--threads |
This flag sets the approximate number of threads to use. A value of 0 (which is the default) causes pseek to choose the thread count using heuristics |
Specifying the Root Directory
To search a specific directory, path can be given as a second argument:
psk error /log
Search Types
Search File Names
psk config --file
Search Directory Names
psk backup --directory
Search File Contents
psk TODO --content
Search Everywhere
psk error
Equivalent to:
psk error --file --directory --content
Query Modes
By default, the query is treated as plain text.
Example:
psk "hello world"
Note: To use case-sensitive, whole-word matching, regular expression search, fuzzy search, and full path search when
--expris enabled, we can use expression prefixes.
Case Sensitive Search
psk Hello --case-sensitive
Matches: Hello
Does not match: hello, HELLO
Whole Word Search
psk cat --word
Matches: cat
Does not match: cats, concatenate
Regular Expression Search
Enable regex mode:
psk "error\d+" --regex
Example matches: error1, error25, error999
Note: Regex matching and whole word matching cannot be used at the same time, because we can use
\bin regex to enable whole word matching:psk "\berror\d+\b" --regex
Fuzzy Search
Fuzzy search allows approximate matching.
Example:
psk apple --fuzzy
Can match: appl, appel, aple
Note: To improve performance, highlighting of matches is automatically disabled if the
--fuzzyflag is enabled and the--wordflag is disabled.
Fuzzy Similarity Threshold
psk apple --fuzzy --fuzzy-level 90
Range: 1-99
Higher values require closer matches.
Examples:
| Level | Strictness |
|---|---|
| 60 | Loose |
| 80 | Recommended |
| 95 | Very strict |
Default: 80
Full Path
By default, Pseek matches file and directory queries against the entry's name only. Use --full-path to match against its full path within the search scope instead. This option affects file and directory searches, not content searches.
For example, given the relative path pseek/utils.py, you can match part of the path rather than just the filename:
# Match against the full relative path
psk "seek/utils" --full-path
Relative paths vs. absolute paths
--full-path does not automatically include the absolute path. If the file's absolute path is:
/home/python/cli/pseek/utils.py
a query such as python/cli will not match unless --absolute-path is also enabled:
psk "python/cli" --full-path --absolute-path
Nested archives
When searching nested archives, --full-path applies only to the path within the current archive level, not the entire nested archive chain.
For example:
archive.zip::folder/arc.zip::fd/file.txt
With --full-path, you can match fd/f against the entry fd/file.txt inside the innermost archive. A query such as zip::fd does not match across archive boundaries. Without --full-path, matching is limited to the entry name, file.txt.
Note: For ordinary queries without
--regex, backslashes are treated literally, so Windows paths can be searched without additional escaping. When using--expr, quoted terms use JSON-style escaping; escape backslashes accordingly. For example,"\\"represents a single literal backslash, while"\\n"represents the literal sequence\n.
Expression Queries
Expression mode enables logical search expressions.
Enable:
psk '("error" or "warning") and not "debug"' --expr
Note: When using
--expr, queries are double-quoted and backslashes have special meaning. Ordinary queries use JSON-style escaping, so\nand\trepresent newline and tab characters, respectively. Use\\nor\\tto search for those literal sequences. Regex queries (r"...") preserve regex escapes, which are interpreted by the regex engine.
Supported Operators
AND
psk '"foo" and "bar"' --expr
Both terms must match.
OR
psk '"foo" or "bar"' --expr
At least one term must match.
NOT
psk 'not "foo"' --expr
Exclude matches containing the term.
PARENTHESES
psk '("foo" or "bar") and not "baz"' --expr
Used for grouping expressions.
Expression Prefixes
Each term can have its own search mode.
Note: For more detailed information about the modes, please refer to the query modes section.
Regex
r"pattern"
Example:
psk 'r"error\d+"' --expr
Case Sensitive
c"text"
Example:
psk 'c"Error"' --expr
Whole Word
w"text"
Example:
psk 'w"cat"' --expr
Fuzzy
f"text"
Example:
psk 'f"apple"' --expr
Full Path
p"text"
Example:
psk 'p"lib"' --expr
Combined Prefixes
Prefixes can be combined.
Examples:
rc"text"
cw"text"
cf"text"
pc"text"
wcf"text"
Example:
psk 'rc"Error\d+"' --expr
Meaning:
- regex
- case-sensitive
simultaneously.
Allowed modes: r, c, w, f, p, rp, pc, wp, fp, rc, cw, cf, wf, cwf, rcp, cwp, cfp, wfp, cwfp
and their permutations.
Note: Whole word matching and regex matching cannot be used at the same time, because we can use
\bin regex to enable whole word matching:r"\btext\b"
Automatic Filtering
Pseek automatically filters files and directories during recursive searches using the same ignore-matching backend and ignore-rule semantics used by ripgrep.
By default, Pseek will ignore all of the following:
- Files and directories that match glob patterns in these sources:
.gitignoreglobs. This includes .gitignore files in parent directories that are part of the same git repository. (Unless the--no-require-gitflag is given).git/info/exclude- Git's global ignore file configured through
core.excludesFile .ignoreglobs, which take precedence over all gitignore globs when there's a conflict. This includes.ignorefiles in parent directories.- Ignore files from parent directories, when applicable (Unless the
--no-ignore-parentflag is given)
- Binary files for content search. (any file with a NUL byte to be binary)
- Hidden files and directories. (A file or directory is considered hidden if its base name starts with a dot character
.) - Symbolic links aren't followed
All of these things can be toggled using various flags:
- You can disable all git-related filtering with the
--no-ignoreflag. - Hidden files and directories can be searched with the
--hiddenflag. - Symbolic links can be searched with the
--followflag.
For convenience, you can use the --unrestricted flag. This flag disables all the automatic filters mentioned above except the filter related to binary files for searching file contents.
The ignore rules are interpreted using the same matching and precedence semantics as ripgrep. When ignore files at different directory levels define conflicting rules, rules from a deeper directory take precedence over rules inherited from its parent directories.
Within the same directory level, ignore sources are applied with the following precedence, from highest to lowest:
.ignore
.gitignore
.git/info/exclude
global Git excludes (core.excludesFile)
Manual Filtering
Globs
Filter files and directories using glob patterns. The --glob option can be specified multiple times to include or exclude paths from the search.
Pseek uses the same Git-style glob syntax and override precedence as ripgrep.
Use a glob without a leading ! to include matching paths:
# Search only Python files
psk TODO --glob '*.py'
# Search Python and Rust files
psk TODO --glob '*.py' --glob '*.rs'
Use a leading ! to exclude matching paths:
# Exclude Python files
psk TODO --glob '!*.py'
# Include Python files, but exclude test files
psk TODO --glob '*.py' --glob '!*.test.py'
Note: The
!prefix has the opposite meaning from its use in.gitignorefiles. With--glob, a pattern without!includes matching paths, while a pattern prefixed with!excludes them.
You can provide multiple --glob options. When multiple patterns match the same path, the last matching pattern takes precedence.
# Include Python files, exclude tests, then include a specific test file
psk TODO \
--glob '*.py' \
--glob '!*.test.py' \
--glob important.test.py
Command-line glob patterns take precedence over Pseek's automatic ignore rules, such as supported .gitignore, .ignore, Git exclude, and global Git ignore rules.
For more details about the ignore rules applied automatically, see Automatic Filtering.
Extension Filters
Include only specific extensions:
psk TODO --ext py --ext js
Exclude extensions:
psk TODO --exclude-ext exe --exclude-ext dll
Path Filters
Include Paths
psk TODO \
--include src \
--include tests
Only search inside those paths.
Note: Paths manually included by the user take precedence over other filters; this means that even if a path conflicts with rules related to --glob, --exclude, etc., it will still be included in the results.
Exclude Paths
psk TODO \
--exclude build \
--exclude .git
Skip those paths.
Note: The include and exclude paths will be combined with path argument.
Regex Path Filters
Include
psk TODO \
--re-include src/.*
Exclude
psk TODO \
--re-exclude "node_modules|dist"
Size Filtering
| Syntax | Meaning |
|---|---|
10m |
exactly 10 MiB |
:10m |
10 MiB or smaller |
10m: |
10 MiB or larger |
10m:20m |
between 10 MiB and 20 MiB |
Both range boundaries are included.
Sizes can be specified using the following units:
| Suffix | Unit |
|---|---|
b |
Bytes |
k |
KiB (1024 bytes) |
m |
MiB (1024^2 bytes) |
g |
GiB (1024^3 bytes) |
t |
TiB (1024^4 bytes) |
Unit suffixes are case-insensitive, so these are equivalent: 10m, 10M
The --size option can be used multiple times. Each size filter is treated as an alternative, meaning that a file only needs to match one of the specified ranges.
For example:
psk config \
--size :1m \
--size 10m:
Files between 1 MiB and 10 MiB will not match.
Note: Directory sizes are not calculated recursively. When
--sizeis used, directories are automatically excluded from the search results.
Depth
Controls how deep the search goes inside directories.
A depth of 0 means that only base path's immediate contents are searched; subdirectories are not entered.
project/ ← base directory
├── file.txt ← depth 0
├── folder1/ ← depth 0
│ ├── file.txt ← depth 1
│ └── folder2/ ← depth 1
│ └── file.txt ← depth 2
--depth can be specified multiple times to search non-contiguous depth ranges:
--depth 0 # Direct contents only
--depth 1 # One level inside
--depth 2:4 # Depths 2 through 4
--depth 2 --depth 5:7 # Depths 2 and 5 through 7
--depth :2 # Depths 0 through 2
--depth 3: # Depth 3 and deeper
If --depth is not specified, the search has no depth limit.
Parallel Search
Pseek can process multiple file paths concurrently to improve search performance, especially when searching large numbers of files.
Use --threads to control the maximum number of worker threads:
# Use the default number of worker threads
psk TODO
# Use 4 worker threads
psk TODO --threads 4
# Use a single worker thread
psk TODO --threads 1
If --threads is not specified, Pseek automatically selects the number of workers based on the available CPU count. Setting --threads 1 disables parallel processing of candidate paths.
More threads do not always mean faster searches. Performance depends on factors such as file sizes, storage speed, and the type of search being performed. You can experiment with different values to find the best setting for your workload.
Note: Parallel processing may change the order in which results are produced. Search filters and matching rules remain unchanged.
Archive Search
Enable archive support:
psk TODO --archive
Supported formats: zip, rar, 7z, gz, bz2, xz, tar, tar.gz, tar.bz2, tar.xz
Note: Automatic filters and --glob option don't work on archive files
Nested Archives
Pseek supports nested archives for multi-file archive containers (zip, rar, 7z, tar and compressed tar formats). Nested archive traversal means Pseek can search inside an archive that itself contains other archives (for example a.zip containing b.7z containing c.tar.gz).
Example:
backup.zip
└── source.7z
└── notes.txt
Pseek can search:
backup.zip::source.7z::notes.txt
Archive Filters
Archive Depth
The concept of depth in archive is different from --depth. Depth in archive is calculated based on nested archives. Each archive that is inside another archive counts as one level of depth.
| Syntax | Meaning |
|---|---|
2 |
exactly 2nd depth |
:2 |
2nd depth or lower |
2: |
2nd depth or higher |
2:4 |
between 2 and 4 (Both range boundaries are included) |
--arc-depth can be specified multiple times:
psk TODO --archive --arc-depth :2 --arc-depth 5:
Meaning archive level 3 and archive level 4 won't be searched.
Note:
--arc-depth 0means perform the search only within this current archive and don't enter nested archives.
Extension Filters
psk TODO --archive --arc-ext py
Only search .py files inside archives.
psk TODO --archive --arc-exc-ext jpg
Exclude .jpg files inside archives.
Path Filters
Include:
psk TODO --archive --arc-include src
Exclude:
psk TODO --archive --arc-exclude cache
Size Filter
This works exactly like the --size option.
psk TODO --archive --arc-size 10m:40m
Note: Archive directory sizes are usually reported as zero by archive formats, so directory search is disabled if this filter is enabled to avoid incorrect results.
RAR Backend
RAR archives require an external helper programs. To enable full support for RAR, either install one of the helper programs in your PATH or provide a backend configuration to Pseek.
Supported backends include:
- UnRAR
- 7-Zip
- BSDTar
- Unar
If one of these is installed and available in PATH, Pseek will detect it automatically when --archive is used and enable archive traversal for RAR files. If not detected, Pseek prints a warning and archive support for that format is disabled.
Use the --rar-backend option to persistently configure a backend and its path.
Examples:
- Linux:
psk unrar --rar-backend /usr/bin/unrar - Windows:
psk unrar --rar-backend "C:\Program Files\WinRAR\UnRAR.exe"
Enter the file type in the query (e.g. unrar, bsdtar, unar, 7z).
Output Options
Show Full Paths
psk TODO --absolute-path
Paths Only
Only display matching file paths:
psk TODO --content --paths-only
Useful for very large result sets.
Context
Show context lines around each match. The value is specified as BEFORE:AFTER:
--context 2 # 2 lines before and after
--context 2:0 # 2 lines before, none after
--context 0:2 # none before, 2 lines after
--context 2:5 # 2 lines before, 5 lines after
--context 2: # 2 lines before, none after
--context :2 # none before, 2 lines after
--context 0 # matching lines only
Nearby matches whose context ranges overlap or directly touch are combined into a single group.
Timeout
Stop the search automatically after a specified number of seconds.
Example:
psk TODO --timeout 0.5
If the search exceeds the limit, it will be terminated. Results found before the search is terminated are still displayed.
Statistics
Display a summary of the search, including result counts, scanned paths, archive information, and search time.
pseek config --stats
Example output:
Statistics
────────────────
Results
Files: 12
Directories matched: 3
Files with matched content: 8
Lines matched: 24
Matches: 31
Search
Files scanned: 1,248
Archives scanned: 5
Directories scanned: 96
Search time: 0.128s
Result Statistics
- Files matched — Number of files whose names matched the query.
- Directories matched — Number of directories whose names matched the query.
- Files with matched content — Number of files containing at least one content match.
- Lines matched — Number of lines containing one or more matches.
- Matches — Total number of matches found in the contents of the files.
Search Statistics
- Files scanned — Number of files examined during the search.
- Archives scanned — Number of archives processed, including nested archives found inside other archives.
- Directories scanned — Number of directories reached and examined during traversal.
When --archive is enabled, file and directory statistics can also include paths inside archives, not just physical paths on the filesystem.
Directories scanned can be 0 when the search path contains no subdirectories. The root search directory itself isn't counted as a scanned directory.
Search time
Time spent performing the search.
When --timeout is used, the statistics represent the work completed before the timeout.
Requirements
- Python
3.10+ unrar,bsdtar,unaror7zipfor the rarfile library to support searching inside.rarfiles (optional)
Metadata
Release files for pseek 3.6.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pseek-3.6.1.tar.gz | 46.4 kB | Without provenance | Details for pseek-3.6.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pseek-3.6.1-cp310-abi3-manylinux_2_28_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.28+ x86-64 | Details for pseek-3.6.1-cp310-abi3-manylinux_2_28_x86_64.whl |
Total release size: 1.0 MB
Release files / pseek-3.6.1.tar.gz
| Download URL | pseek-3.6.1.tar.gz |
|---|---|
| Size | 46.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e815cb08fade00939b0335869e45c5414b314aefe3b5c0de3453ccf2119a09fc
|
|
BLAKE2b-256 checksum How to use checksums |
9e816a64bdbdcf233f82f4d585ad6dcda586eb378fb37e2f238eccb5b0dc4095
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pseek-3.6.1-cp310-abi3-manylinux_2_28_x86_64.whl
| Download URL | pseek-3.6.1-cp310-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 962.4 kB |
| Tags | CPython 3.10 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
74436613463ef7b0d5548a447b3eaaaf2ccd8f5c4ace79e6725559ee473142a3
|
|
BLAKE2b-256 checksum How to use checksums |
70f81e0481e9480b88c0131710b1ebfc9eea474e73d13444c87dc3ad295a0625
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for pseek 3.6.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.