sillystrings
A Python reimplementation of the Unix strings utility. Extracts printable character sequences from binary files with support for multiple encodings, offset display, and standard CLI conventions.
Pure Python, zero dependencies, comprehensive test coverage.
Installation
Requires Python 3.11+.
Install from source using uv:
git clone https://github.com/jkomalley/sillystrings.git
cd sillystrings
uv sync
Usage
sillystrings [OPTIONS] [FILE ...]
With no file arguments, reads from stdin.
Options
| Flag | Description |
|---|---|
-n NUM |
Minimum string length (default: 4) |
-e {s,S,l,b,L,B} |
Character encoding: s = 7-bit ASCII (default), S = 8-bit, l = UTF-16 LE, b = UTF-16 BE, L = 32-bit LE, B = 32-bit BE |
-t {d,o,x} |
Print byte offset before each string in decimal, octal, or hex |
-o |
Same as -t o |
-a, --all |
Scan the whole file (the default) |
-d, --data |
Scan only the data sections of an object file; see below |
-w |
Also include newlines, vertical tabs, form feeds, and carriage returns in strings (tab and space always are) |
-f |
Print the filename before each string |
-v |
Show version and exit |
Scanning only data sections
By default every byte of a file is scanned. With -d, sillystrings follows GNU
strings -d: when the file is an object it recognizes, only the sections
loaded into memory from the file are scanned, and each section is scanned on its
own, so a string never runs across a section boundary. Offsets are still from
the start of the file.
| Mode | Recognized object | Anything else |
|---|---|---|
default, -a |
Whole file | Whole file |
-d |
Data sections | Whole file |
-a and -d override each other, so the last one given wins. Thin Mach-O
and ELF files (32- and 64-bit, either byte order) are recognized. With -d:
- "Data" means every section loaded with content from the file, code
included. Zero-filled sections (such as
__bssand.bss) are skipped, and so are sections that aren't loaded, such as debug info and ELF's.commentand.symtab(.dynsymis loaded, so it is scanned). - A section whose bytes lie outside the file is skipped, and the rest are scanned.
- Everything else is scanned whole: fat (universal) Mach-O files, static
archives (
.a), ELF core dumps, ELF files with no section headers (such as aftersstrip), objects with no data sections, files that aren't a recognized object or can't be parsed, and stdin.
Unlike GNU, where - is another spelling of -a, a - argument here means
stdin.
This is GNU's behavior, not macOS strings'. Apple's strings parses Mach-O
by default, skips only (__TEXT,__text), reads just one slice of a fat file,
and uses -a to mean all sections, so its output differs from both modes here.
Examples
Scan a binary for readable strings:
sillystrings /usr/bin/ls
Show hex offsets with 8-bit encoding:
sillystrings -t x -e S firmware.bin
Scan only the data sections of an object file:
sillystrings -d build/main.o
Read from stdin:
cat firmware.bin | sillystrings -
Find wide (UTF-16 LE) strings with a minimum length of 8:
sillystrings -e l -n 8 program.exe
Architecture
The project is organized into four layers:
- encodings -- character-level printability checks for ASCII and 16- and 32-bit wide characters
- scanner -- accumulates printable runs into strings, tracks byte offsets
- formats -- parses object file formats to find the data sections
-dscans - cli -- argument parsing, file I/O, output formatting
Development
just install # or: uv sync && uv run pre-commit install
just check # format, lint, type check, and the test suite
Tests cover all encoding modes, offset calculations, CLI flags, edge cases, and integration via subprocess.
See CONTRIBUTING.md for development setup, project layout, and the conventions this repo follows.
License
MIT
Metadata
Release files for sillystrings 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sillystrings-0.2.0.tar.gz | 19.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sillystrings-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.7 kB
Release files / sillystrings-0.2.0.tar.gz
| Download URL | sillystrings-0.2.0.tar.gz |
|---|---|
| Size | 19.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eb55c68eb6a109926eb837e6279b53ef2e3e9e2564c85aba0ec16d7f4e6b041e
|
|
BLAKE2b-256 checksum How to use checksums |
584922c07e54297c600c47ce5d484b417ba5d11f4cf969230dd179f9d098e8b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / sillystrings-0.2.0-py3-none-any.whl
| Download URL | sillystrings-0.2.0-py3-none-any.whl |
|---|---|
| Size | 23.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1a737e6a4a1750a2da902cc1537b43917e75c1e4bf5edc8d31d09a69fe27606e
|
|
BLAKE2b-256 checksum How to use checksums |
afa598656dd337ab138c87961d20e2d125df0471cea2e9c8eaa07a16d0a916b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency log