I found a plugin that does this for me: Additional image sizes (zui)
When you delete an image size that size will not be created for all NEW images you upload.
However, images created for deleted sizes still exist on the server as well as the image attachment metadata for those sizes.
This feature will physically delete those images from the server as well as the image attachment meta data for those sizes.
Use this feature at your own risk. There is no undo.
Update
While the plugin worked wonders and did a lot of cleanup it couldnt cleanup the files left behind by images that had been removed from WordPress in the past. I used this home brew script to clean up some of the left over images:
<?php
$files = find_all_files("/home/****/public_html/wp-content/uploads");
$files2 = array();
foreach($files as $key => $file) {
if(1 == preg_match("#150x\d+\.jpg$#", $file)) {
$files2[] = $file;
unlink($file);
}elseif(1 == preg_match("#300x\d+\.jpg$#", $file)) {
$files2[] = $file;
unlink($file);
}elseif(1 == preg_match("#\d+\x300.jpg$#", $file)) {
$files2[] = $file;
unlink($file);
}elseif(1 == preg_match("#\d+\x150.jpg$#", $file)) {
$files2[] = $file;
unlink($file);
}elseif(1 == preg_match("#\d+\x1024.jpg$#", $file)) {
$files2[] = $file;
unlink($file);
}
}
print_r($files2);
function find_all_files($dir)
{
$root = scandir($dir);
foreach($root as $value)
{
if($value === '.' || $value === '..') {continue;}
if(is_file("$dir/$value")) {$result[]="$dir/$value";continue;}
foreach(find_all_files("$dir/$value") as $value)
{
$result[]=$value;
}
}
return $result;
}
?>