{"id":21995558,"url":"https://github.com/chriscummins/shutterbug","last_synced_at":"2025-07-08T05:07:04.023Z","repository":{"id":57467030,"uuid":"79268498","full_name":"ChrisCummins/shutterbug","owner":"ChrisCummins","description":"📷 + 💿 = Archive photos on discs for safekeeping","archived":false,"fork":false,"pushed_at":"2018-05-06T14:04:12.000Z","size":16,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-28T10:45:16.170Z","etag":null,"topics":["backup-solution","dvd","photos"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChrisCummins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-17T20:25:43.000Z","updated_at":"2018-05-06T14:04:13.000Z","dependencies_parsed_at":"2022-09-10T03:43:00.446Z","dependency_job_id":null,"html_url":"https://github.com/ChrisCummins/shutterbug","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisCummins%2Fshutterbug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisCummins%2Fshutterbug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisCummins%2Fshutterbug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisCummins%2Fshutterbug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChrisCummins","download_url":"https://codeload.github.com/ChrisCummins/shutterbug/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245053635,"owners_count":20553366,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backup-solution","dvd","photos"],"created_at":"2024-11-29T21:16:49.337Z","updated_at":"2025-03-23T04:21:32.415Z","avatar_url":"https://github.com/ChrisCummins.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shutterbug\n\nShutterbug splits a large collection of photos into a series of DVD-sized folders for burning to disc, and provides a mechanism to go from these disc backups back to the original directory structure.\n\nShutterbug is paranoid about data loss and corruption, and has some coping\nstrategies:\n\n* It maintains a 1-1 mappings so that 1 input file = 1 file on a disc. This\n  means if a file becomes corrupted, you lose one image. Other approaches which\n  do not respect file boundaries lead to losing multiple images in one go.\n* It randomizes the order of the files on the discs so that if a disc is lost,\n  you end up with lots of tiny gaps in your photo library, not one big one.\n* It validates your files after restoring from backup, so you have a warning of\n  data corruption. Note this does not **prevent** data loss, only **discovers**\n  it. *The best way to prevent irrecoverable data loss is to make more copies of\n  your data to begin with.*\n\n## Usage\n\n### Requirements\n\n* Python 3.\n\n### Installation\n\n```\n$ pip3 install shutterbug\n```\n\n### Archiving to disc\n\nTo backup your photo library in `~/Pictures/2016` to 4.7GB DVDs, split the folder into \"chunks\" using shutterbug:\n\n```\n$ mkdir ~/chunks \u0026\u0026 cd ~/chunks\n$ shutterbug ~/Pictures/2016 --gzip\nchunk_001/ae3d47f87af176b74e1ec30599a7b31a.jpg.gz 4.93MB -\u003e 4.90MB\nchunk_001/631600d1e11339794e81d75f104e9f19.jpg.gz 7.40MB -\u003e 7.38MB\nchunk_001/130c52fe396237a59500a61b8101ff55.jpg.gz 6.79MB -\u003e 6.77MB\nchunk_001/27fc10914e18b0e1b303c05a800c299d.jpg.gz 5.73MB -\u003e 5.70MB\n...\nWrote chunk_001/MANIFEST.txt\nWrote chunk_001/README.txt\nchunk_001 has 723 files, size 4662.40 MB (99.2% of maximum size)\n\nchunk_002/5c9ce3b8071207ab702766ac2be76f10.jpg.gz 6.13MB -\u003e 6.11MB\nchunk_002/bc17480a318e7ba9a3e4e2e57538917d.jpg.gz 9.63MB -\u003e 9.60MB\n...\n```\n\nBurn each of the resulting folders in `~/chunks` to DVDs.\n\n### Restoring from disc\n\nCopy each chunk from your DVDs back to disc, e.g. `~/import/chunk_001`,\n`~/import/chunk_002` etc. Restore the original file structure by running\nshutterbug from the output directory:\n\n```\n$ mkdir ~/Pictures/2016 \u0026\u0026 cd ~/Pictures/2016\n$ shutterbug --unpack ~/import/chunk_*\n$ ~/Pictures/mkbackup.py ../compressed/* -u\n~/import/chunk_001/ae3d47f87af176b74e1ec30599a7b31a.jpg.gz -\u003e ./2016-12 NYC (2434 of 5025).jpg\n~/import/chunk_001/631600d1e11339794e81d75f104e9f19.jpg.gz -\u003e ./2016-12 NYC (4411 of 5025).jpg\n~/import/chunk_001/130c52fe396237a59500a61b8101ff55.jpg.gz -\u003e ./2016-12 NYC (301 of 5025).jpg\n...\n```\n\nShutterbug will print warnings for files in case the size or contents have\nchanged.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchriscummins%2Fshutterbug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchriscummins%2Fshutterbug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchriscummins%2Fshutterbug/lists"}