Skip to content

Instantly share code, notes, and snippets.

@zmwangx
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmwangx/47ba8ca9bfe3ec11f70f to your computer and use it in GitHub Desktop.
Save zmwangx/47ba8ca9bfe3ec11f70f to your computer and use it in GitHub Desktop.
Automatically clean up the "Previous Mobile Applications" folder created by iTunes. https://zmwangx.github.io/blog/2015-06-27-automatically-clean-up-previous-mobile-applications.html
#!/usr/bin/env python3
"""Periodically clean up "Previous Mobile Applications" of iTunes."""
import arrow
import datetime
import json
import os
import sys
OFFENDING_DIR = os.path.expanduser("~/Music/iTunes/iTunes Media/Mobile Applications/Previous Mobile Applications")
STORAGE_DIR = os.path.expanduser("~/.local/share/itunes")
STORAGE_FILE = os.path.join(STORAGE_DIR, "previous-mobile-applications.json")
DELETE_AFTER = datetime.timedelta(days=7)
def load_storage():
"""Load stored dictionary of seen apps from STORAGE_FILE.
Returns
-------
seen_app_dict : dict
Dictionary of (app_filename, first_seen_date) key-value pairs,
where app_filename is str, and last_seen_date is datetime.date.
"""
os.makedirs(STORAGE_DIR, mode=0o700, exist_ok=True)
try:
with open(STORAGE_FILE, encoding="utf-8") as fp:
serializable_seen_app_dict = json.load(fp)
return {app_filename: arrow.get(serialized_first_seen_date).date()
for app_filename, serialized_first_seen_date in serializable_seen_app_dict.items()}
except OSError:
return {}
def write_storage(seen_app_dict):
"""Write the dictionary of seen apps to STORAGE_FILE.
Parameters
----------
seen_app_dict : dict
See the return format of load_storage().
Returns
-------
0 or 1
Return code indicating success or failure.
"""
# convert datetime.time to str (ISO 8601)
serializable_seen_app_dict = {app_filename: first_seen_date.isoformat()
for app_filename, first_seen_date in seen_app_dict.items()}
os.makedirs(STORAGE_DIR, mode=0o700, exist_ok=True)
try:
with open(STORAGE_FILE, mode="w", encoding="utf-8") as fp:
json.dump(serializable_seen_app_dict, fp, indent=2, sort_keys=True)
return 0
except OSError as err:
sys.stderr.write("error: failed to write to '%s': %s" % (STORAGE_FILE, str(err)))
return 1
def main():
"""Main.
Returns
-------
0 or 1
Return code indicating success or failure.
"""
if not os.path.isdir(OFFENDING_DIR):
# good, you don't have that junk
return 0
today = datetime.date.today()
seen_app_dict = load_storage()
current_app_list = os.listdir(OFFENDING_DIR)
# boot already disappeared apps
for app in [app for app in seen_app_dict if app not in current_app_list]:
seen_app_dict.pop(app)
# add newly appeared apps
for app in [app for app in current_app_list if app not in seen_app_dict]:
seen_app_dict[app] = today
# delete expired apps
returncode = 0
newly_deleted_apps = []
for app in seen_app_dict:
if today >= seen_app_dict[app] + DELETE_AFTER:
app_path = os.path.join(OFFENDING_DIR, app)
try:
os.remove(app_path)
newly_deleted_apps.append(app)
except OSError as err:
sys.stderr.write("error: failed to remove '%s': %s" % (app_path, str(err)))
returncode = 1
for app in newly_deleted_apps:
seen_app_dict.pop(app)
# write data to disk
returncode |= write_storage(seen_app_dict)
return returncode
if __name__ == "__main__":
exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment