Skip to content
lespeaPublic

About

Dumps the fseventsd entries from a mac

Resources

Stars

8 stars

Watchers

2 watching

Forks

Repository files navigation

fse_dump

FSEvents files are written to disk by macOS APIs and contain historical records of file system activity that occurred for a particular volume. They can be found on devices running macOS and devices that were plugged in to a device running macOS. fse_dump can be used to parse FSEvents files from the /System/Volumes/Data/.fseventsd/ on a live system or FSEvents files extracted from an image.

Github CI Github Release Crates.io

Features

  • Parse FSEvents files from macOS (versions 1, 2, and 3)
  • Export to multiple formats: CSV, JSON, YAML
  • Filter events by path (regex) and flags
  • Compress output with gzip or zstd
  • Watch mode for real-time parsing of new FSEvents files
  • Generate unique path/operation summaries
  • Fast parallel processing with memory-efficient design

Installation

From crates.io

cargo install fse_dump

From source

git clone https://github.com/lespea/fse_dump
cd fse_dump
cargo build --release

Features

zstd, watch, hex, and extra_id are enabled by default; alt_flags is opt-in.

# Everything (adds alt_flags)
cargo install fse_dump --all-features

# A smaller build without watch mode or zstd
cargo install fse_dump --no-default-features --features hex,extra_id

Quick Start

Parse FSEvents to JSON

# Parse default FSEvents directory to JSON
fse_dump dump --json output.json

# Parse with compression
fse_dump dump --json output.json.gz

# Parse specific files
fse_dump dump --json output.json /path/to/fsevent/file1 /path/to/file2

Filter Events

# Filter by path (regex)
fse_dump dump --json output.json -p "\.pdf$"

# Filter by any of the specified flags
fse_dump dump --json output.json -f Created Modified

# Filter requiring all specified flags
fse_dump dump --json output.json --all-flags FileEvent Modified

# Combine filters (paths are relative to the volume root, so no leading slash)
fse_dump dump --json output.json \
  -p "^Users/" \
  -f Created Removed

Watch Mode

# Watch for new FSEvents files and output as JSON
fse_dump watch

# Watch with filters
fse_dump watch -o json -P \
  -p ".*\.docx?$" \
  -f Modified

Usage

Usage: fse_dump <COMMAND>

Commands:
  dump      Dump fsevents file into the wanted output files/format
  watch     Watch for new fse files, parse them, and write them to the desired output
  generate  Outputs shell completions for the desired shell
  help      Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

Dump Command

The dump command parses FSEvents files and outputs them in various formats.

fse_dump dump [OPTIONS] [FILES]...

Arguments

  • [FILES]... - The FSEvents files to parse (default: /System/Volumes/Data/.fseventsd/)
    • Can be individual files or directories
    • Directories are scanned for files with hex-only filenames
    • Files are sorted by name before processing

Output Format Options

Individual File Output (creates output file next to each input file):

  • --csvs - Create .csv file for each FSEvents file
  • --jsons - Create .json file for each FSEvents file
  • --yamls - Create .yaml file for each FSEvents file

Combined Output (all records in one file):

  • -c, --csv <FILE> - Write all records to a single CSV file
  • -j, --json <FILE> - Write all records to a single JSON file
  • -y, --yaml <FILE> - Write all records to a single YAML file
  • -u, --uniques <FILE> - Write unique paths with combined operations to CSV

Use - as the filename to write to stdout:

fse_dump dump --json - | jq .

Compression Options

Automatic Compression (based on file extension):

# Gzip compression (automatic)
fse_dump dump --json output.json.gz

# Zstd compression (automatic, requires zstd feature)
fse_dump dump --json output.json.zst

Force Compression:

  • --gzip - Force gzip compression (even for stdout)
  • --zstd - Force zstd compression (requires zstd feature)
  • -l, --glevel <0-9> - Gzip compression level (default: 7)
  • --zlevel <0-20> - Zstd compression level (default: 10)
  • --zthreads <N> - Zstd threads (default: 2, 0 to disable)

Time Filtering

  • -d, --days <N> - Only process files modified in the last N days (default: 90)
    • Set to 0 to process all files regardless of age
    • Based on file modification/creation time
    • Applies to files found by scanning a directory; files named explicitly are always parsed
    • A warning reports how many files were skipped, and the run fails if nothing is left to parse (common when parsing files extracted from an image long after they were written)

Event Filtering

Filter which events are included in the output:

Path Filtering:

  • -p, --path-filter <REGEX> - Only include events matching the regex pattern

Paths in FSEvents logs are stored relative to the volume root, so a file at /Users/alice/notes.txt appears as Users/alice/notes.txt. Anchor patterns with ^Users/, not ^/Users/.

# Only PDF files
fse_dump dump --json output.json -p "\.pdf$"

# Only files under the Users directory
fse_dump dump --json output.json --path-filter "^Users/"

# Multiple patterns (use regex alternation)
fse_dump dump --json output.json -p "\.(pdf|docx?|xlsx?)$"

Flag Filtering:

  • -f, --any-flags <FLAG>... - Include events with ANY of these flags
  • --all-flags <FLAG>... - Include events with ALL of these flags

These options are mutually exclusive.

Available Flags:

Flag Description
FolderEvent Event occurred on a folder
Mount Volume was mounted
Unmount Volume was unmounted
EndOfTransaction End of a transaction
LastHardLinkRemoved Last hard link to file removed
HardLink Hard link created
SymbolicLink Symbolic link created
FileEvent Event occurred on a file
PermissionChange Permissions were changed
ExtendedAttrModified Extended attributes modified
ExtendedAttrRemoved Extended attributes removed
DocumentRevisioning Document versioning event
ItemCloned Item was cloned
Created File/folder was created
Removed File/folder was removed
InodeMetaMod Inode metadata modified
Renamed File/folder was renamed
Modified File/folder was modified
Exchange Files exchanged
FinderInfoMod Finder info modified
FolderCreated Folder was created

Flag names are case-insensitive.

Examples:

# Find all file creation or removal events
fse_dump dump --json output.json -f Created Removed

# Find all modified files (not folders)
fse_dump dump --json output.json --all-flags FileEvent Modified

# Find files created in the Documents folder
fse_dump dump --json output.json \
  -p "/Documents/" \
  -f Created

# Find permission changes on system files
fse_dump dump --json output.json \
  -p "^(System|Library)/" \
  -f PermissionChange

Complete Examples

# Parse last 30 days to compressed JSON
fse_dump dump --days 30 --json events.json.gz

# Create CSV and JSON for each FSEvents file
fse_dump dump --csvs --jsons

# Export unique paths to CSV
fse_dump dump --uniques unique_paths.csv

# Parse specific file to stdout with filters
fse_dump dump --json - \
  -p "^Users/alice/" \
  -f Modified Created \
  /path/to/fsevent/file

# Multiple outputs with compression
fse_dump dump \
  --json all_events.json.gz \
  --csv all_events.csv.gz \
  --uniques unique_paths.csv \
  --days 7

Watch Command

The watch command monitors directories for new FSEvents files and parses them in real-time.

fse_dump watch [OPTIONS] [WATCH_DIRS]...

Arguments

  • [WATCH_DIRS]... - Directories to watch (default: /System/Volumes/Data/.fseventsd/)

Options

  • -o, --format <FORMAT> - Output format: csv, json, or yaml (default: json)
  • -P, --pretty - Pretty-print JSON output (multi-line formatting)
  • --poll - Use polling instead of native file system events (slower but more compatible)

Compression options (same as dump command):

  • --gzip, --zstd, -l, --glevel, --zlevel, --zthreads

Filtering options (same as dump command):

  • -p, --path-filter <REGEX>
  • -f, --any-flags <FLAG>...
  • --all-flags <FLAG>...

Examples

# Watch default directory and output JSON to stdout
fse_dump watch

# Watch with pretty-printed JSON
fse_dump watch -o json -P

# Watch and filter for document changes
fse_dump watch \
  -p "\.(doc|pdf|txt)$" \
  -f Modified Created

# Watch custom directory with CSV output
fse_dump watch -o csv /custom/fsevents/path

# Watch with compression (pipe to file); Ctrl-C or SIGTERM finishes the stream cleanly,
# and a second one exits at once
fse_dump watch --gzip > events.json.gz

Only files whose names are made of hex digits (how fseventsd names its logs) are parsed; fseventsd-uuid and anything else in the directory is ignored.

Generate Command

Generate shell completion scripts for various shells.

fse_dump generate <SHELL>

Supported Shells

  • bash
  • elvish
  • fish
  • powershell
  • zsh

Examples

# Generate completions for bash
fse_dump generate bash > ~/.local/share/bash-completion/completions/fse_dump

# Generate completions for zsh
fse_dump generate zsh > ~/.zsh/completions/_fse_dump

# Generate completions for fish
fse_dump generate fish > ~/.config/fish/completions/fse_dump.fish

Output Format

Record Fields

Each FSEvents record contains the following fields:

{
  "path": "Users/alice/Documents/file.txt",
  "event_id": "0x12AB34CD",
  "flags": "FileEvent | Modified",
  "node_id": "0x56EF78",
  "extra_id": "0x9ABC",
  "file_timestamp": "2023-05-24T10:30:00Z"
}
  • path - Full path to the file/folder
  • event_id - Unique event identifier (hex format if built with hex feature). fseventsd names each log after the event id that follows its last record, so every id in a file is below the file name.
  • flags - Human-readable flag names separated by |
  • alt_flags - Alternative flag interpretation (if built with alt_flags feature)
  • node_id - Inode number (v2 and v3 only, hex format if built with hex feature)
  • extra_id - Additional ID (v3 only, requires extra_id feature). Other parsers label this field a UID, but in captured data it is 0 for most records and otherwise matches the numeric component of .docid/…/changed/N/ paths, so treat the meaning as unconfirmed.
  • file_timestamp - Modification time of the source FSEvents file (ISO 8601)

Unique Output Format

The --uniques option produces aggregated records (CSV format):

path,counts,flags,earliest_timestamp,latest_timestamp
Users/alice/file.txt,5,"FileEvent | Modified | Created",2023-05-24T10:30:00Z,2023-05-24T11:45:00Z
Users/alice/Documents,3,"FolderEvent | Modified",2023-05-24T09:15:00Z,2023-05-24T10:00:00Z
  • path - The file/folder path
  • counts - Number of events for this path
  • flags - Combined flags (bitwise OR of all events)
  • alt_flags - Combined alternative flags (if built with alt_flags feature)
  • earliest_timestamp - Earliest event time (requires --unique-timestamps)
  • latest_timestamp - Latest event time (requires --unique-timestamps)

YAML Output Format

When exporting to YAML, fse_dump produces a multi-document stream, where each record is separated by ---. This allows for efficient streaming processing of large outputs.

---
path: Users/alice/file.txt
event_id: "0x123"
flags: Created
---
path: Users/alice/file.txt
event_id: "0x124"
flags: Modified

Exit Status

fse_dump exits non-zero if anything went wrong: an input that could not be read or parsed (including a truncated log), an output file that could not be created, a write failure, invalid options, or an input list that expanded to no files. A bad input does not stop the others from being parsed, and the records read from a truncated log before the cut are still written. Errors are logged to stderr as they happen; the final message states how many occurred.

Advanced Usage

Filtering Complex Scenarios

Find all deletions in user directories:

fse_dump dump --json deletions.json \
  -p "^Users/" \
  -f Removed

Find renamed files (with old and new names):

fse_dump dump --json renames.json \
  -f Renamed

Monitor system configuration changes:

fse_dump dump --json system_changes.json \
  -p "^(System|Library|private/etc)/" \
  -f Modified PermissionChange

Find cloned/copied files:

fse_dump dump --json clones.json \
  -f ItemCloned

Combining with Other Tools

jq for JSON processing:

# Extract just the paths
fse_dump dump --json - | jq -r '.path'

# Find events for a specific user
fse_dump dump --json - | jq 'select(.path | startswith("Users/alice"))'

# Count events by flag
fse_dump dump --json - | jq -r '.flags' | sort | uniq -c

grep/awk for quick filtering:

# Find all PDF operations
fse_dump dump --json - | grep '\.pdf"'

# CSV processing with awk
fse_dump dump --csv - | awk -F',' '$3 ~ /Created/ {print $1}'

Performance Tips

  1. Use compression for large outputs to save disk space
  2. Use --days to limit processing to recent files
  3. Apply filters early with --path-filter and --any-flags to reduce output size
  4. Use CSV for the most compact output format
  5. Use --uniques when you only need summary statistics

Forensics Use Cases

Timeline analysis:

# Export everything from last 7 days
fse_dump dump --days 7 --json timeline.json.gz

Malware detection (find suspicious file operations):

# Find new executables
fse_dump dump --json suspicious.json \
  -p "\.(app|exe|sh|command|pkg|dmg)$" \
  -f Created

# Find hidden files
fse_dump dump --json hidden.json \
  -p "/\.[^/]+$" \
  -f Created Modified

Data exfiltration (find removable media):

# Monitor mounts/unmounts
fse_dump dump --json removable.json \
  -f Mount Unmount

User activity:

# Monitor specific user's home directory
fse_dump dump --json user_activity.json \
  -p "^Users/targetuser/" \
  --days 30

Building from Source

Features

Default features: zstd, watch, hex, extra_id. Opt-in: alt_flags.

  • zstd - Enable zstd compression support
  • watch - Enable watch mode for real-time monitoring (pulls in notify)
  • hex - Output numeric IDs in hexadecimal format
  • alt_flags - Include the alternative (mac_apt style) flag names as a second column
  • extra_id - Include extra_id field from v3 files
# Trim the default set
cargo build --release --no-default-features --features "hex,extra_id"

# Build with all features
cargo build --release --all-features

Development

# Run tests
cargo test

# Run with debug logging (debug-level messages are compiled out of release builds)
RUST_LOG=debug cargo run -- dump --json output.json

# Lint and test every feature combination the way CI does
just ci

# Check code
cargo clippy
cargo fmt

References

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Dumps the fseventsd entries from a mac

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages