Skip to content

Instantly share code, notes, and snippets.

@fischerscode
Created May 13, 2025 21:25
Show Gist options
  • Save fischerscode/a8e68a675ebb0524a4a4761bdd810f95 to your computer and use it in GitHub Desktop.
Save fischerscode/a8e68a675ebb0524a4a4761bdd810f95 to your computer and use it in GitHub Desktop.
Extracts all files from a .mcfx SQLite package into a directory.
#!/usr/bin/env python3
"""
mcfx_extractor.py: Extracts all files from a .mcfx SQLite package into a directory.
The .mcfx format is a SQLite database with a table:
Files(Filename TEXT PRIMARY KEY, Data BLOB, LastModified INTEGER)
This script reads each entry and writes it out preserving folder structure and timestamps.
Usage:
python mcfx_extractor.py path/to/book.mcfx -o output_directory
"""
import os
import sqlite3
import argparse
def extract_mcfx(mcfx_path, output_dir):
# Ensure output directory exists
os.makedirs(output_dir, exist_ok=True)
# Connect to the SQLite database
conn = sqlite3.connect(mcfx_path)
cursor = conn.cursor()
# Fetch all files
cursor.execute("SELECT Filename, Data, LastModified FROM Files")
rows = cursor.fetchall()
for filename, data, lastmod in rows:
# Determine full path and create any necessary directories
file_path = os.path.join(output_dir, filename)
os.makedirs(os.path.dirname(file_path), exist_ok=True)
# Write blob data to file
with open(file_path, 'wb') as f:
f.write(data)
print(f"Extracted: {filename}")
# Set file modification time if available
if lastmod:
# lastmod may be in milliseconds
ts = float(lastmod)
if ts > 1e10: # likely milliseconds
ts = ts / 1000.0
# Set both access and modification times
os.utime(file_path, (ts, ts))
conn.close()
def main():
parser = argparse.ArgumentParser(description="Extract contents of a .mcfx package")
parser.add_argument('mcfx', help='Path to the .mcfx file')
parser.add_argument('-o', '--output', default='output', help='Directory to extract files into')
args = parser.parse_args()
extract_mcfx(args.mcfx, args.output)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment