Documentation
¶
Overview ¶
detect.go is the top-level file analyser for winfile.
[analyseFile] is the entry point: it stats the path, handles Windows special files (symlinks, directories, named pipes, sockets), opens the file, reads the magic-byte window, and delegates to [doAnalyse].
[doAnalyse] runs the two-pass detection pipeline:
- Magic-byte scan via [detectMagic] (magic.go).
- Text-encoding scan via [detectText] (text.go) if magic returns nil.
If neither pass succeeds the file is reported as "data" with MIME type application/octet-stream.
Compression unwrapping (-z / -Z flags)
When [options.uncompress] is set and the outer format is gzip or bzip2, [decompressFirst] streams the first magicBufSize bytes of the inner payload and runs the two-pass detection on that buffer. The outer compression type is appended to the description unless [options.uncompressNoreport] is set. XZ is identified at the outer level but inner unwrapping is not supported (no XZ decoder in the Go standard library).
Text refinement ¶
[refineText] narrows a generic ASCII/UTF-8 result to a specific language or format using two signals: JSON structural heuristic first, then the file extension as a secondary hint. The extension table covers ~60 languages and markup formats. A separate base-name table handles extension-less files such as Makefile and Dockerfile.
Access-time preservation (-p flag)
When [options.preserveDate] is set, a deferred os.Chtimes call restores the modification time after the file is read. (Windows does not expose the atime separately via Go's os.Lstat, so mtime is used as the best available approximation.)
elf.go implements GNU file(1)-compatible reporting for ELF binaries.
GNU file describes an ELF image in two halves:
ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, ... `------------ header fields -------------' `------ whole-file fields ------'
The header half comes from the first 64 bytes (class, byte order, object type, machine, ELF version, OS/ABI). The rest requires walking the program headers, the section headers and the note records, which are scattered through the whole file.
[elfDetail] therefore has two paths:
- [elfAnalyse] opens the file with debug/elf and produces the full GNU description. It needs a seekable path.
- [elfHeaderOnly] uses just the magic-byte window and stops after the OS/ABI. It is the fallback for stdin, pipes and anything debug/elf refuses to parse.
The layout of the description follows file(1) closely enough that the two can be diffed line by line; see the "GNU file compatibility" section of README.md for the deliberate differences.
magic.go implements magic-byte file-type detection.
[detectMagic] reads up to 512+256 bytes from the start of a file and matches them against a table of well-known binary signatures ("magic numbers"). Each entry maps a byte pattern at a fixed offset to a human- readable description, a MIME type string, and a canonical extension.
Format families covered: executables (PE, ELF, Mach-O), archives and compression (ZIP/OOXML, gzip, bzip2, XZ, zstd, LZ4, 7-Zip, RAR, tar, Cabinet), images (PNG, JPEG, GIF, BMP, TIFF, WebP, AVIF/HEIF, ICO, PSD, PPM/PGM/PBM), audio (WAV, FLAC, Ogg/Vorbis/Opus, MP3, MIDI, AIFF), video (AVI, MP4/MOV/M4V, MKV/WebM, FLV, ASF, MPEG), documents (PDF, PostScript, OLE2, RTF), databases (SQLite, Access), bytecode (Java .class, Python .pyc), fonts (TTF, OTF, WOFF, WOFF2), disk images (ISO 9660, MBR, VMDK, VHD/VHDX, QCOW2), and cryptographic containers (PEM, DER).
Format-specific sub-detectors (peDetail, elfDetail, zipDetail, …) inspect additional header fields to produce richer descriptions—e.g. PE files report CPU architecture and EXE-vs-DLL, ZIP containers report OOXML sub-type (DOCX/XLSX/PPTX/JAR/EPUB), and Ogg streams report codec (Vorbis/Opus/Theora/Speex).
winfile is a Windows port of the classic Unix `file` command.
It identifies the type of one or more files by examining their content (magic bytes, encoding heuristics, and structural markers) rather than relying on file extensions alone. Output is compatible with the GNU file command so it can be used as a drop-in replacement in scripts and pipelines on Windows.
Usage:
winfile [OPTION...] FILE...
Common options:
-b brief output (no filename prefix) -i output MIME type string (e.g. image/png; charset=binary) --mime-type output MIME type only --mime-encoding output charset / encoding only --extension output slash-separated list of valid extensions -f FILE read filenames from FILE (one per line) -L follow symbolic links -z look inside compressed files (gzip, bzip2) -Z like -z but omit the compression wrapper from the description -0 NUL-terminate output records (for use with xargs -0)
See [usage] for the full option list.
Detection coverage ¶
Binary formats: PE (EXE/DLL), ELF (reported in GNU file's full detail — linkage, interpreter, build ID, ABI tag, stripped state, core-dump provenance; see elf.go), Mach-O, ZIP and OOXML derivatives (DOCX/XLSX/PPTX/JAR/APK/EPUB), gzip, bzip2, XZ, zstd, LZ4, 7-Zip, RAR, tar (POSIX ustar), PNG, JPEG, GIF, BMP, TIFF, WebP, AVIF/HEIF, ICO, PDF, PostScript, OLE2 (legacy Office), SQLite, Java .class, MKV/WebM, MP4/MOV, AVI, FLAC, Ogg (Vorbis/Opus/Theora), WAV, MIDI, TTF/OTF/WOFF/WOFF2, PEM certificates, and many more.
Text formats: ASCII, UTF-8, UTF-16 LE/BE (BOM-detected), UTF-32 LE/BE; Go, Python, JavaScript/TypeScript, JSX/TSX, Java, C/C++, C#, Rust, Ruby, PHP, Perl, Shell, PowerShell, Batch, Lua, HTML, XML, SVG, CSS/SCSS, JSON, YAML, TOML, Markdown, SQL, Dockerfile, Makefile, and more—detected by content first, extension as a secondary hint.
text.go implements text-file encoding detection.
[detectText] scans a byte sample and attempts to classify it as human- readable text, returning the character encoding and a short description compatible with GNU file output.
Detection order:
- UTF-32 BOM (FF FE 00 00 / 00 00 FE FF)
- UTF-16 BOM (FF FE / FE FF)
- UTF-8 BOM (EF BB BF)
- Heuristic scan over up to 8 KiB: count NUL bytes, non-UTF-8 sequences, and control characters. Files with >1 % NUL or >5 % invalid bytes are classified as binary (nil return). Otherwise the result is ASCII if no high bytes appear, or UTF-8 otherwise.
CRLF line endings are noted separately in the description when found, to match GNU file behaviour on Windows-style text files.
[looksLikeJSON] is a lightweight check used by the text-refinement stage in detect.go to promote plain-text files to the JSON MIME type when the content starts with '{' or '['.