Updated about 8 yrs, 3 mths ago (August 13, 2016). Know a better answer? Let me know!
Delete Photos without Descriptions from Google Photos
How to delete photos without descriptions from Google Photos using a Greasemonkey/Tampermonkey script.
Google Photos is quite rubbish and has almost no useful features, but at the same time is quite useful due to their unlimited free hosting of photos.
I made the mistake of uploading a heap of photos without descriptions, and then adding descriptions to my local copies of the photos. The Google Uploader then sees the photos as different, and re-uploads them.
To manually go through and delete photos without descriptions would take months… so I hacked together this Greasemonkey script to do it for me.
Note that it is very hacky, the timings and delays have been tweaked to work on my current internet connection speed, there is very little error checking, it may or may not actually work for you, and it may somehow delete all your photos… so use with extreme caution.
It makes a button when you are viewing photos, which if you click it, tries to check if the photo has a description, and then clicks the Next Photo button. If it doesn’t have a description, it clicks the delete icon, and then the remove button, and then does it all over again…
When it all goes horribly wrong, which it does frequently, it waits a short while, clicks the Previous Photo button, and then tries again.
It also adds a quick delete button, which automatically clicks Delete and then the Remove button to make deleting photos quicker.
// ==UserScript== // @name Delete Google Photos // @namespace photos.google.com // @description Delete Google Photos with blank descriptions // @include https://photos.google.com/photo/* // @include https://photos.google.com/u/*/photo/* // @include https://photos.google.com/search/* // @include https://photos.google.com/u/*/search/* // @version 1 // @grant none // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js // ==/UserScript== this.$ = this.jQuery = jQuery.noConflict(true); $(document).ready(function() { var nedSearchDeletePhotos = { count: { deleted: 0, kept: 0 }, run: false, init: function() { // add a button this.button = $('<button style="position:fixed;top:20px;left:160px;z-index:9000">Search and delete empty descriptions</button>').on('click', function() { if(confirm("Are you sure?")) { nedSearchDeletePhotos.click(); } }).appendTo('body'); // add delete button $('<button style="position:fixed;top:20px;left:100px;z-index:9000">[DEL]</button>').on('click', function() { $('div:visible[aria-label="Delete"]').click(); // click confirm setTimeout(function() { $('span:visible').filter(function() { return ($(this).text() === 'Remove'); }).click(); }, 250); }).appendTo('body'); }, click: function() { if(this.run) { this.stop(); } else { this.start(); } }, start: function() { this.run = true; this.doSearch(); }, stop: function() { this.button.text('[Stopped: Click to start] Kept: ' + this.count.kept + ' Deleted: ' + this.count.deleted); this.run = false; }, doSearch: function() { if(!this.run) { console.log('Stopping'); return; } // update button count this.button.text('[Started: Click to stop] Kept: ' + this.count.kept + ' Deleted: ' + this.count.deleted); var description = $('textarea:visible[placeholder="Add a description"]'), filename = $('div:visible[aria-label^="Filename:"]').text(); if(description && filename) { if(description.val()) { console.log('KEEP', filename, description.val()); this.count.kept++; // get next this.next(); } else { // check it is not an auto creation // PANO|ANIMATION|EFFECTS|HDR|COLLAGE|MOTION if(filename.match(/PANO|ANIMATION|EFFECTS|HDR|COLLAGE|MOTION|MOV|AVI|MPEG|MPG|MP4/i)) { console.log('EFFECT', filename, description.val()); this.count.kept++; this.next(); } else { console.log('DELETE', filename, description.val()); // delete this.del(); } } } else { console.log('No description or filename fields found. Retry in 1 seconds'); //this.setTimeout(function() { // go back $('div[aria-label="View previous photo"]').click(); nedSearchDeletePhotos.setTimeout(function() { nedSearchDeletePhotos.doSearch(); }, 1000); //}, 2500); } }, del: function() { // delete // setTimeout(function() { $('div:visible[aria-label="Delete"]').click(); // click confirm this.setTimeout(function() { $('span:visible').filter(function() { return ($(this).text() === 'Remove'); }).click(); // console.log('Delete clicked'); nedSearchDeletePhotos.count.deleted++; // timeout and next // next automatically called by Google when deleting nedSearchDeletePhotos.setTimeout(function() { nedSearchDeletePhotos.doSearch(); }, 2500); }, 250); // }, 1000); }, next: function() { // setTimeout(function() { var next = $('div[aria-label="View next photo"]'); next.click(); // run it all again this.setTimeout(function() { nedSearchDeletePhotos.doSearch(); }, 750); // }, 1000); }, setTimeout: function(fn, time) { var that = nedSearchDeletePhotos; if(that.timer) { clearTimeout(that.timer); } that.timer = setTimeout(fn, time); } }; nedSearchDeletePhotos.init(); });
More Information
Information above gathered from the following sources:
Updated about 8 yrs, 3 mths ago (August 13, 2016). Know a better answer? Let me know!
Related categories
.Comment on this article (no HTML, max 1200 characters):