#!/usr/bin/env python
#
# This works for me. It probably won't work for you, but if it does, cool.
#
import argparse
import glob
import os
from pathlib import Path
import subprocess
import sys
#
# set up the defaults…
#
BACKUP_DIR = '/Volumes/8SI/Dropbox/Modelers/Fractal Audio/Backups'
ZIP = '/usr/bin/zip'
TOUCH = '/usr/bin/touch'
VERBOSE_OR_NOT = False
#
# The array elements should be in UPPERCASE…
#
IIIMk2_FILES = sorted([
'BANK-A', 'BANK-B', 'BANK-C', 'BANK-D', 'BANK-E', 'BANK-F', 'BANK-G', 'BANK-H',
'SYSTEM+GB+FC',
'USER-CAB-BANK-1', 'USER-CAB-BANK-2',
'USER-CAB-BANK-FR'
])
FM9_FILES = sorted([
'BANK-A', 'BANK-B', 'BANK-C', 'BANK-D',
'SYSTEM+GB+FC',
'USER-CAB-BANK-1'
])
FM3_FILES = sorted([
'BANK-A', 'BANK-B', 'BANK-C', 'BANK-D',
'SYSTEM+GB+FC',
'USER-CAB-BANK-1'
])
#
# Strip the extension from filenames. Fold to UPPERCASE…
#
def get_backup_filetypes(files):
return [Path(f).stem.split('-', 3)[-1].upper() for f in files]
#
# Is the list of files being backed up a full or partial backup?
# Compare using UPPERCASE.
#
def is_partial_backup(files):
device = files[0].split('-')[0]
match device.upper():
case 'FM3':
required_files = FM3_FILES
case 'FM9':
required_files = FM9_FILES
case 'IIIMK2':
required_files = IIIMk2_FILES
case _:
sys.exit(f"{device} is an unknown device type.")
return sorted(get_backup_filetypes(files)) != required_files
# -----------------
# FIRE IN THE HOLE!
# -----------------
def main() -> int:
#
# Grab any command-line options…
#
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--dir', help='the path to the directory containing backup .syx files',
default=BACKUP_DIR)
parser.add_argument('-t', '--testrun',
help='testrun only', action='store_true')
parser.add_argument('-v', '--verbose', help='run verbosely',
action='store_true', default=VERBOSE_OR_NOT)
args = parser.parse_args()
working_dir = os.getcwd()
if args.verbose:
print(f"chdir {args.dir}")
os.chdir(args.dir)
#
# Get the *.syx files
#
syx_files = sorted(glob.glob('*.syx'))
if len(syx_files) == 0:
if args.verbose:
print(f'chdir {working_dir}')
os.chdir(working_dir)
sys.exit('No .syx files exist. Back something up!')
#
# Get the unique device_yyyymmdd_hhmmss stamps as a hash of
# the device+datestamp+timestamp => [files that match]
#
uniq_backups = {}
for sf in syx_files:
backup_device = '-'.join(sf.split('-')[0:3])
if backup_device not in uniq_backups:
uniq_backups[backup_device] = []
uniq_backups[backup_device].append(sf)
#
# We know what files to expect from a full backup. If we don't have them
# all then label it with "partial".
#
for k, v in uniq_backups.items():
zipfile = k
if is_partial_backup(v):
zipfile += '-partial'
zipfile += '.zip'
yymmdd, hhmmss = k.split('-')[1:3]
hhmm = hhmmss[0:4]
ss = hhmmss[-2:]
# Do things…
for cmd in [
f"{ZIP} -m {zipfile} {' '.join(v)}",
f"{TOUCH} -ct \"{yymmdd}{hhmm}.{ss}\" {zipfile}"
]:
if args.verbose or args.testrun:
print(cmd)
if not args.testrun:
subprocess.run(cmd, shell=True, check=True)
if args.verbose:
print(f"chdir {working_dir}")
os.chdir(working_dir)
return 0
if __name__ == '__main__':
sys.exit(main())