The code below takes two command line arguments, an absolute folder path and integer, which is the minimum number of qualifying photos in each folder required to return a positive search result.
Saves/prints to screen a dictionary containing the path of the photo containing folders and the paths of the images within them. The search is recursive.
I thought this could be useful as a step towards grabbing all those forgotten photos on my computers and those of relatives etc(all I do here is fetch each photo's location).
#! python3
# Recursively searches the given folder for photos which meet the defined
# criteria
# Prints search results to screen and saves said data as a pickled object and
# as a reader friendly .txt file using pprint
import argparse
import logging
import os
import pickle
import pprint
from PIL import Image
logging.basicConfig(level=logging.INFO, format="%(asctime)s - " +\
"%(levelname)s - %(message)s")
logging.disable(logging.CRITICAL)
def check_size(images: list, min_dimension: int):
"""Returns a list of all photos which meet dimension requirements
"""
photos = [image for image in images if min(Image.open(image).size) >
min_dimension]
return photos
def find_images(filenames: list, folder: str, formats: list):
"""Returns list of image abspaths for a folder if format in 'formats'"""
all_images = [os.path.join(folder, file) for file in filenames if
file.lower().endswith(tuple(formats))]
return all_images
def handle_input():
"""Parses and returns user input with guidance to correct input format"""
parser = argparse.ArgumentParser()
parser.add_argument("folder", type=str,
help="the folder (this folder's subfolders will " +
"also be searched) to search for photo files.")
parser.add_argument("min_num_photos", type=int,
help="The minimum number of photos required to be " +
"present in a folder for that folders's data to be " +
"saved and displayed.")
args = parser.parse_args()
return args.folder, args.min_num_photos
def photo_search(folder: str, min_photos: int):
"""Return data structure of all folders with 'min_photos' photos
"""
# photo formats
formats = ["jpg", "png"]
# minimum qualifying size of any dimension(height, width)
min_dimension = 500
# store positive results of search in dict data structure
data = {}
for folder, subfolders, filenames in os.walk(folder):
# get list of all images in folder
all_images = find_images(filenames, folder, formats)
logging.info("all_images: {}".format(all_images))
# get a list of all photos present in folder
photos = check_size(all_images, min_dimension)
logging.info("photos: {}".format(photos))
# append data to data dict if min requirements met
if len(photos) > min_photos:
#folder_dict = {"photos": photos, "number": len(photos)}
data[folder] = {"photos": photos, "number": len(photos)}
return data
def save_data(data: dict, folder: str):
"""Saves a data dict to file as pickled obj and readable .txt file"""
# save pickled object
with open(os.path.join(folder, "results.dat"), "wb") as f:
pickle.dump(data, f)
# save reader friendly text version of data
with open(os.path.join(folder, "results.txt"), "w") as f:
f.write(pprint.pformat(data))
def main():
"""Performs a recursive search of a folder for photos meeting a defined
criteria
"""
# save search results to following folder
save_folder = r"C:\Users\Dave\Desktop\2016Coding\AutomateBoring" +\
r"\17-ManipulatingImages\photo_search"
# if save folder doesn't exist, create
if not os.path.exists(save_folder):
os.mkdir(save_folder)
folder, min_photos = handle_input()
# perform a search of folder for photo files by walking the folder tree
data = photo_search(folder, min_photos)
# save data as pickled object and as reader-friendly .txt file
save_data(data, save_folder)
# print reader friendly version of 'data' to screen
pprint.pprint(data)
print("\n*****Done*****\n")
if __name__ == "__main__":
main()
endswith
takes a tuple to denote anor
relationship. \$\endgroup\$ – Graipher Dec 8 '16 at 11:29