Exporting Files
Creating a Backup in Paperparrot
If you want to export your files from Paperparrot, you should first create a backup from Paperparrot.
To do so, head to the settings tab and tap the "Back up local database" option:

Save the ZIP archive to any convenient location. You can also use this backup to restore Paperparrot in the future.
Retrieving Original Files From the Backup
The backup contains the SQLite Database for both Paperparrot and your custom queries and a (hidden) directory with support files (this will contain most of your documents).
You can use any SQLite compatible database viewer to inspect the contents of the databases.
To conveniently export all files from the backup archive, you can use the following Python script:
The entire python code is also available at the bottom of this article.
To use the script, put it in the same directory the Paperparrot backup is in and execute it using the terminal:
python3 extract_files.py <name-of-the-zip>
For example:
python3 extract_files.py export.zip
When done, you will see a new directory output containing all the original files you added to Paperparrot.
Entire Script Code
from zipfile import ZipFile
import shutil
import sqlite3
from pathlib import Path
from mimetypes import guess_extension
import os
import re
import argparse
def export_files(db_name: str, base_path: str = "", output_dir: str = "output"):
support_dir = f'.{db_name.strip(".sqlite")}_SUPPORT'
with sqlite3.connect(os.path.join(base_path, db_name)) as conn:
cur = conn.cursor()
res = cur.execute('''
SELECT ZTITLE, ZTYPE, ZCD_DOCUMENT_DATA.ZDATA
FROM ZCD_DOCUMENT
INNER JOIN ZCD_DOCUMENT_DATA on ZCD_DOCUMENT.ZDATA = ZCD_DOCUMENT_DATA.Z_PK;
''')
Path(output_dir).mkdir(parents=True, exist_ok=True)
for row in res:
title = row[0]
extension = guess_extension(row[1])
data = row[2]
output_path = os.path.join(output_dir, title + extension)
if len(data) == 38:
uuid = data[1:-1].decode()
original_path = os.path.join(
base_path, support_dir, "_EXTERNAL_DATA", uuid)
shutil.copyfile(original_path, output_path)
else:
with open(output_path, 'wb') as fw:
fw.write(data)
print(f'Saved document "{title}" to {output_path}')
def extract_backup_and_export_files(zip_name: str):
regex = re.compile('Paperparrot-\\d{8}T\\d{6}.sqlite')
backup_path = os.path.join("temp", "backup")
with ZipFile(zip_name, 'r') as zObject:
zObject.extractall("temp")
sqlite_file = None
for _, _, files in os.walk(backup_path):
for file in files:
if regex.match(file):
sqlite_file = file
if sqlite_file is None:
print("Couldn't find database in backup, cleaning up...")
else:
export_files(sqlite_file, backup_path)
shutil.rmtree("temp")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="Paperparrot Backup Helper",
description="Exports all files from a Paperparrot backup")
parser.add_argument(
"filename", help="Name of the zip file exported from Paperparrot")
args = parser.parse_args()
extract_backup_and_export_files(args.filename)