Skip to content

Instantly share code, notes, and snippets.

@tamask
Last active November 17, 2020 19:10
Show Gist options
  • Save tamask/8ba578d3a788aa0c60db9163676ccc94 to your computer and use it in GitHub Desktop.
Save tamask/8ba578d3a788aa0c60db9163676ccc94 to your computer and use it in GitHub Desktop.
Utility script for downloading photos/images from the iPhone. Optionally converts HEIC files to JPG with `heif-convert` util. Meant for Linux but could work elsewhere. `heif-convert` is available through the `libheif-examples` package on Ubuntu, for example.
#!/usr/bin/env python
# HEIC image conversion depends on the heif-convert cmd utility,
# available through the `libheif-examples` package on Ubuntu, for example.
import os
import glob
import argparse
import datetime
import shutil
import subprocess
def fetch_iphone_photos(
source_dir, target_dir,
from_date=None, to_date=None,
include=tuple(), exclude=tuple(),
convert_heic=False):
'''
from_date and to_date are formated as 'YYYY-MM-DD' or None
include and exclude are a list of extensions, i.e. ('png', 'jpg', 'mov')
'''
if from_date is not None:
from_date = datetime.date.fromisoformat(from_date)
if to_date is not None:
to_date = datetime.date.fromisoformat(to_date)
if include:
include = [ext.upper() for ext in include]
if exclude:
exclude = [ext.upper() for ext in exclude]
for path in glob.iglob(os.path.join(source_dir, '**'), recursive=True):
file_basename = os.path.basename(path)
file_name, file_ext = os.path.splitext(file_basename)
path_date = datetime.date.fromtimestamp(os.path.getmtime(path))
if os.path.isdir(path):
continue
if from_date and path_date < from_date:
continue
if to_date and to_date > to_date:
continue
file_ext = file_ext[1:].upper()
if include:
if file_ext not in include:
continue
elif exclude:
if file_ext in exclude:
continue
target_subdir = os.path.join(target_dir, path_date.strftime('%Y/%m/%d'))
os.makedirs(target_subdir, exist_ok=True)
if file_ext == 'HEIC' and convert_heic:
target_path = os.path.join(target_subdir, '%s.JPG' % file_name)
subprocess.run(['heif-convert', '-q', '100', path, target_path], check=True)
shutil.copystat(path, target_path)
else:
target_path = os.path.join(target_subdir, file_basename)
shutil.copy2(path, target_path)
print('%s --> %s' % (path, target_path))
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=(
'Fetch photos from iPhone, optionally convert HEIC. '
'Uses [TARGET-DIR]/YYYY/MM/DD/<file> directory format. '
'This is a utility script meant to help get photos into Shotwell.'
))
parser.add_argument(
metavar='SOURCE-DIR', dest='src_dir',
help='DCIM folder on iPhone')
parser.add_argument(
metavar='TARGET-DIR', dest='dst_dir',
help='Location to copy photos to')
parser.add_argument(
'--from', dest='from_date', default=None,
help='Optional start date cutoff for the copy. Format is YYYY-MM-DD.')
parser.add_argument(
'--to', dest='to_date', default=None,
help='Optional end date cutoff for the copy. Format is YYYY-MM-DD.')
parser.add_argument(
'--include', dest='include', action='append',
help='Only include the given file extension. Option can be used multiple times.')
parser.add_argument(
'--exclude', dest='exclude', action='append',
help='Exclude the given file extension. Option can be used multiple times.')
parser.add_argument(
'--convert-heic', dest='convert_heic', default=False, action='store_true',
help='Convert source HEIC to JPG in target dir. Requires the heif-convert util.')
args = parser.parse_args()
fetch_iphone_photos(
args.src_dir, args.dst_dir,
from_date=args.from_date, to_date=args.to_date,
include=args.include, exclude=args.exclude,
convert_heic=args.convert_heic)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment