How to make a single gallery from nested folders

I often see a single photo/art gallery with a nested folder structure that Stash treats as multiple galleries.

For example, Stash would look at a structure like this and make galleries of the 6 innermost folders that have pictures:

Cosplayer/
    March 2022/
        Gwen Stacy/
            Cosplay Photoset/
            Boudoir Photoset/
            Backstage/
            Videos/
        Marin Kitagawa/
            Cosplay Photoset/
            Boudoir Photoset/
            Backstage/
            Videos/

The innermost folder structure is important, but it is not the most natural grouping, and causes related items to get separated in the app.

If you create a zip file of each related gallery, it will preserve the file structure within that zip file and Stash will treat it as a single gallery. But you don’t want to include videos in the zip file as they will not be seen by Stash or CBZ viewers.

        Gwen Stacy/
            Gwen Stacy.cbz
            Videos/
        Marin Kitagawa/
            Marin Kitagawa.cbz
            Videos/

Here is a script to make a single uncompressed zip file from all images in a folder and its subfolders, without also including videos.

#!/bin/sh -e -u

# make-cbz.sh
# Create a .CBZ file of all the images in a directory.
# Leave non-image files in place.

# Example:
# > make-cbz.sh images/
# ...
# Created images.cbz

# Example: zip all subdirectories
# > for f in */; do make-cbz.sh "$f"; done
# ...
# Created a.cbz
# Created b.cbz
# Created c.cbz

echo
DIR="$1"
shift
if [ ! -d "$DIR" ]; then
	echo Error: "$DIR" is not a directory. Cancelled.
	exit 1
fi

# Work relative to parent folder of dir, to simplify path within zip file.
cd "$DIR"
DIR="$(basename "$PWD")"
cd ..

# Check whether this zipfile has already been created.
ZIPFILE="${DIR%/}.cbz"
if [ -f "$ZIPFILE" ]; then
	echo Error: "$ZIPFILE" already exists. Cancelled.
	exit 2
fi
if [ -f "${DIR}/$(basename "$ZIPFILE")" ]; then
	echo "$ZIPFILE" already exists within "$DIR". Skipped.
	exit 0
fi
echo Creating "$ZIPFILE"...


# Simple command to zip only common image suffixes
# zip -0 --latest-time -m -r "$ZIPFILE" "$DIR" \
# 	-i '*.jpeg' -i '*.jpg' -i '*.gif' -i '*.png' -i '*.svg' -i '*.webp' \
# 	-i '*.JPEG' -i '*.JPG' -i '*.GIF' -i '*.PNG' -i '*.SVG' -i '*.WEBP'

# Function to identify image files based on contents
function list_images() {
	local IFS="$(printf "\x1E\n")"
	find "$1" -exec file --separator "$IFS" {} \; \
		| grep -i "image data" \
		| cut -d "$IFS" -f 1 - \
		| sort --version-sort
}

if [ -z "$(list_images .)" ]; then
	echo No image files found in "$DIR". Skipped.
	exit 0
fi

# Zip identified images with no compression, and remove original files
list_images "$DIR" | zip -0 --latest-time -m "$ZIPFILE" -@

if [ ! -f "$ZIPFILE" ]; then
	echo Error: "$ZIPFILE" was not created.
	exit 3
fi
echo Created "$ZIPFILE"

# Remove empty folders.
find "$DIR" -name ".DS_Store" -delete
find "$DIR" -type d -empty -delete

# If main directory was not empty, move zipfile into it to stay with related files.
if [ -d "$DIR" ]; then
	mv "$ZIPFILE" "$DIR"/
	echo Moved "$ZIPFILE" into "$DIR/"
fi

2 Likes