Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Nautilus Thumbnail Generator. Python 3 scalable and fast.
#!/usr/bin/python3
import concurrent.futures
import hashlib
import os
import sys
import gi
gi.require_version('GnomeDesktop', '3.0')
from gi.repository import Gio, GnomeDesktop
def make_thumbnail(factory, filename, overwrite=False):
mtime = os.path.getmtime(filename)
# Use Gio to determine the URI and mime type
f = Gio.file_new_for_path(filename)
uri = f.get_uri()
info = f.query_info('standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
mime_type = info.get_content_type()
# Already thumbnailed
path = factory.lookup(uri, mtime)
if overwrite and path is not None:
print("Removed:" + path)
os.remove(path)
if (not overwrite) and (path is not None):
return False
# Not thumbnailable
if not factory.can_thumbnail(uri, mime_type, mtime):
return False
# Error during thumb
thumbnail = factory.generate_thumbnail(uri, mime_type)
if thumbnail is None:
print("Error thumbnailing: " + str(uri))
return False
factory.save_thumbnail(thumbnail, uri, mtime)
return True
def thumbnail_targets(factory, targets: list, overwrite=False):
tcount = os.cpu_count() * 2
with concurrent.futures.ThreadPoolExecutor(max_workers=tcount) as tpe:
n_created = 0
nails = tpe.map(lambda name: make_thumbnail(factory, name, overwrite=overwrite), targets)
for n, f in enumerate(nails):
update_txt = "Thumbnailing: {:.2%}".format((n + 1) / len(targets))
print(update_txt, end="\r")
n_created += f
print("\nThumbnailed %i files." % n_created)
def gather_paths(targets: list, ignore_dot_prefixed=True):
file_names = []
for target in targets:
if os.path.isdir(target):
for dirpath, folders, filenames in os.walk(target):
# Skip recursion into dotfiles if requested
# This helps with windows/osx FS/trash/etc
if ignore_dot_prefixed:
for folder in folders:
if folder.startswith("."):
folders.remove(folder)
# Append files found to list
for filename in filenames:
file_names.append(os.path.join(dirpath, filename))
continue
if os.path.isfile(target):
file_names.append(target)
continue
raise ValueError("Don't know what to do with: " + target)
file_names.sort()
print(file_names)
return file_names
if __name__ == '__main__':
import argparse
ap = argparse.ArgumentParser(
description="A tool for generating Gnome thumbnails in parallel.")
ap.add_argument(
"paths",
help="The path(s) to thumbnail (typically one or more folders)",
nargs="+")
ap.add_argument(
"--overwrite",
help="Overwrite existing thumbnails.",
action="store_true")
ap.add_argument(
"--dotfiles",
help="Don't ignore directories prefixed with '.'",
action="store_false")
parsed = ap.parse_args()
factory = GnomeDesktop.DesktopThumbnailFactory()
targets = gather_paths(parsed.paths, ignore_dot_prefixed=parsed.dotfiles)
print("%i targets found" % len(targets))
thumbnail_targets(factory, targets, overwrite=parsed.overwrite)
@meawoppl

This comment has been minimized.

Copy link
Owner Author

@meawoppl meawoppl commented Jan 5, 2020

I added proper arg parsing and overwrite ability.

@barureddy

This comment has been minimized.

Copy link

@barureddy barureddy commented Mar 3, 2020

This is exactly what I needed for previewing thousands of large images quickly. Thanks!

@meawoppl

This comment has been minimized.

Copy link
Owner Author

@meawoppl meawoppl commented Mar 3, 2020

I'm glad you like it. I'm surprised the default gnome config doesn't support any concurrency in this. Feel free to share, and lmk if it needs any improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment