Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Run thumbnailer for arbitrary paths

For some reason, it's complex to tell a thumbnailer program to index arbitrary paths, such as a single directory or even single file. I don't relish using dbus, but begrudgingly use it to accomplish some goals. I'm pragmatic, to a degree.

Apparently tools like tumbler need dbus to receive messages about what paths to index.

So I vibecoded some syntax for dbus commands and some filetypes for a find operation, and wrote some functions that I find useful.

files/2026/listings/thumbnail_functions.sh (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/bin/sh
# File: thumbnail_functions.sh
# Location: https://bgstack15.ddns.net/blog/posts/2026/08/30/run-thumbnailer-for-arbitrary-paths/
# Author: bgstack15
# Startdate: 2026-08-17-2 19:29
# Title: Functions for Thumbnail Operations
# Purpose: Store all thumbnail operations in one location
# History:
# Usage:
#    source this file, and call the functions you want
#    . thumbnail_functions.sh
#    thumbnail_dir ~/Downloads
# Reference:
#    man busctl
# Improve:
# Dependencies:
#    A thumbnailer implementation, perhaps tumbler
# Documentation:
#    Running these commands in other windows:
#       busctl --user monitor org.freedesktop.thumbnails.Thumbnailer1
#       G_MESSAGES_PREFIXED= G_MESSAGES_DEBUG=all /usr/lib/x86_64-linux-gnu/tumbler-1/tumblerd
#    Bare command:
#       busctl --user call org.freedesktop.thumbnails.Thumbnailer1 /org/freedesktop/thumbnails/Thumbnailer1 org.freedesktop.thumbnails.Thumbnailer1 Queue asasssu 2 file:///home/bgstack15/Downloads/godzilla.jpg file:///home/bgstack15/Downloads/mary-had-a-little-lamb.jpg 2 "image/jpeg" "image/jpeg" "xx-large" "" 0
#       gdbus call --session --dest org.freedesktop.thumbnails.Thumbnailer1 --object-path /org/freedesktop/thumbnails/Thumbnailer1 --method org.freedesktop.thumbnails.Thumbnailer1.Queue "['file:///home/bgstack15/Downloads/godzilla.jpg']" "['image/jpeg']" "normal" "[]" "0"
#       WARNING: dbus-send does not correctly handle commas in the filenames. I was unable to discover how to escape the comma.
#       dbus-send --dest=org.freedesktop.thumbnails.Thumbnailer1 /org/freedesktop/thumbnails/Thumbnailer1 org.freedesktop.thumbnails.Thumbnailer1.Queue array:string:"file:///path/to/your/file.jpg" array:string:"image/jpeg" string:"normal" string:"leave-on-disk" uint32:0

thumbnail_dir() {
    _dir="${DIR:-${1:-.}}"
    _size="${THUMBNAIL_SIZE:-${2:-normal}}"
    _recursive="${RECURSIVE}"
    _max_depth="${MAX_DEPTH:-1}"
    if test -z "${_recursive}" ;
    then
        if echo " ${@} " | grep -qiE -e ' -r | --recursive ' 1>/dev/null 2>&1 ;
        then
            # safety max depth.
            _max_depth=10
        fi
    fi
    _infiles="$(
        find "${_dir}" -mindepth 1 -maxdepth "${_max_depth}" -type f \( \
            -iname '*.png' -o -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.webp' -o -iname '*.gif' \
            -o -iname '*.bmp' -o -iname '*.tif' -o -iname '*.tiff' -o -iname '*.svg' -o -iname '*.avif' \
            -o -iname '*.heic' -o -iname '*.ico' -o -iname '*.jp2' -o -iname '*.jxl' -o -iname '*.apng' \
            \) -print0 \
        | sed -r -e 's/ /%20/g;' | xargs -0 -I{} printf '%s ' "{}"
    )"

    _uris="$(
        for _word in ${_infiles} ; do
            printf '"file://%s" ' "${_word}"
        done
    )"

    _mimetypes="$(
        for _word in ${_infiles} ; do
            _n="$( echo "${_word}" | sed -r -e 's/%20/ /g;' )"
            file -b --mime-type "${_n}" | xargs -I{} printf '%s ' "{}"
        done
    )"

    _len="$( printf '%s\n' "${_infiles}" | wc -w )"
    eval busctl --user call org.freedesktop.thumbnails.Thumbnailer1 /org/freedesktop/thumbnails/Thumbnailer1 \
        org.freedesktop.thumbnails.Thumbnailer1 Queue \
        "asasssu" \
        "${_len}" "${_uris}" \
        "${_len}" "${_mimetypes}" \
        "${_size}" \
        "\"\"" \
        0
}

thumbnail_file() {
    _file="${FILE:-${1}}"
    _size="${THUMBNAIL_SIZE:-${2:-normal}}"
    _mimetype="$( file -b --mime-type "${_file}" 2>/dev/null )"
    _file="$( echo "${_file}" | sed -r -e 's/ /%20/g;' )"
    busctl --user call org.freedesktop.thumbnails.Thumbnailer1 /org/freedesktop/thumbnails/Thumbnailer1 \
        org.freedesktop.thumbnails.Thumbnailer1 Queue \
        "asasssu" \
        "1" "file://${_file}" \
        "1" "${_mimetype}" \
        "${_size}" \
        "" \
        0
}

So now I can run the following, to force the thumbnailer to interpret a directory.

. ./thumbnail_functions.sh
thumbnail_dir ~/Downloads

Comments