144 lines
6.3 KiB
Bash
144 lines
6.3 KiB
Bash
#!/bin/bash
|
|
|
|
# Enhanced NAS cleanup script with thumbnail protection
|
|
# Usage: ./nascleanup.sh /volume1/Hydra/path/to/directory
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo "Usage: $0 <directory_path>"
|
|
echo "Example: $0 /volume1/Hydra/Creative/artsy"
|
|
exit 1
|
|
fi
|
|
|
|
TARGET_DIR="$1"
|
|
|
|
# Merge synoindexd layout .../<file>/@eaDir/*.jpg into .../<file>/ (Synology Drive expects no inner @eaDir).
|
|
flatten_indexer_layout() {
|
|
local root="$1"
|
|
[ -d "$root" ] || return 0
|
|
find "$root" -mindepth 2 -type d -name '@eaDir' -print0 2>/dev/null | while IFS= read -r -d '' NEST; do
|
|
PARENT="$(dirname "$NEST")"
|
|
[ -d "$NEST" ] || continue
|
|
for f in "$NEST"/*; do
|
|
[ -e "$f" ] || continue
|
|
base="$(basename "$f")"
|
|
[ "$base" = "SYNOINDEX_MEDIA_INFO" ] && continue
|
|
mv -f "$f" "$PARENT/" 2>/dev/null || true
|
|
done
|
|
rm -rf "$NEST" 2>/dev/null || true
|
|
done
|
|
}
|
|
|
|
# Copy one thumbgen tree: PARENT/eaDir_tmp -> PARENT/@eaDir (psthumbgen uses per-folder eaDir_tmp).
|
|
promote_one_eadir_tmp() {
|
|
local EADIR_TMP="$1"
|
|
local PARENT TARGET_AT SRC_JPG DST_JPG
|
|
PARENT="$(dirname "$EADIR_TMP")"
|
|
TARGET_AT="$PARENT/@eaDir"
|
|
[ -d "$EADIR_TMP" ] || return 0
|
|
chmod -R 755 "$EADIR_TMP" 2>/dev/null || true
|
|
find "$EADIR_TMP" -type f -exec chmod 644 '{}' \; 2>/dev/null || true
|
|
echo " -> Flattening eaDir_tmp (indexer may have added .../<file>/@eaDir/) before copy: $EADIR_TMP"
|
|
flatten_indexer_layout "$EADIR_TMP"
|
|
echo " -> Replacing $EADIR_TMP -> $TARGET_AT"
|
|
SRC_JPG=$(find "$EADIR_TMP" -type f -name 'SYNO*.jpg' 2>/dev/null | wc -l | tr -d '[:space:]')
|
|
rm -rf "$TARGET_AT"
|
|
mkdir -p "$TARGET_AT"
|
|
if ! cp -R "$EADIR_TMP/." "$TARGET_AT/"; then
|
|
echo "ERROR: eaDir_tmp -> @eaDir copy failed (see cp messages above)."
|
|
exit 1
|
|
fi
|
|
echo " -> Flattening @eaDir after copy (same layout fix)"
|
|
flatten_indexer_layout "$TARGET_AT"
|
|
DST_JPG=$(find "$TARGET_AT" -type f -name 'SYNO*.jpg' 2>/dev/null | wc -l | tr -d '[:space:]')
|
|
if [ "$SRC_JPG" -gt 0 ] && [ "$DST_JPG" -ne "$SRC_JPG" ]; then
|
|
echo "ERROR: Promote incomplete: $DST_JPG SYNO*.jpg in @eaDir vs $SRC_JPG in eaDir_tmp (expected equal)."
|
|
exit 1
|
|
fi
|
|
chmod -R 755 "$EADIR_TMP" 2>/dev/null || true
|
|
find "$EADIR_TMP" -type f -exec chmod u+w '{}' \; 2>/dev/null || true
|
|
find "$EADIR_TMP" -type d -exec chmod u+w '{}' \; 2>/dev/null || true
|
|
rm -rf "$EADIR_TMP" 2>/dev/null || sudo -n rm -rf "$EADIR_TMP" 2>/dev/null || true
|
|
}
|
|
|
|
echo "=== Enhanced Synology Thumbnail Cleanup ==="
|
|
echo "Target directory: $TARGET_DIR"
|
|
|
|
# 1. Stop indexing services temporarily
|
|
echo "Stopping indexing services (best effort)..."
|
|
# Non-login SSH often has a minimal PATH; binary lives in /usr/syno/sbin
|
|
if [ -x /usr/syno/sbin/synoservicectl ]; then
|
|
SYNOCTL=/usr/syno/sbin/synoservicectl
|
|
elif command -v synoservicectl >/dev/null 2>&1; then
|
|
SYNOCTL=synoservicectl
|
|
else
|
|
SYNOCTL=""
|
|
fi
|
|
if [ -n "$SYNOCTL" ]; then
|
|
"$SYNOCTL" --stop synoindexd 2>/dev/null || true
|
|
"$SYNOCTL" --stop pkgctl-SynoFinder 2>/dev/null || true
|
|
elif command -v systemctl >/dev/null 2>&1; then
|
|
# Plain `systemctl` as non-root usually fails silently; try sudo -n first (NOPASSWD).
|
|
for u in synoindexd pkgctl-SynoFinder; do
|
|
sudo -n systemctl stop "$u" 2>/dev/null || systemctl stop "$u" 2>/dev/null || true
|
|
done
|
|
else
|
|
echo " -> Service control unavailable; skipping"
|
|
fi
|
|
|
|
# 2. Clear indexing queue to prevent regeneration
|
|
echo "Clearing indexing queue (if accessible)..."
|
|
if [ -w /var/spool ]; then
|
|
rm -f /var/spool/syno_indexing_queue* 2>/dev/null || true
|
|
fi
|
|
|
|
# 3. Dry-run check (see what @eaDir directories exist)
|
|
echo "=== Existing @eaDir directories ==="
|
|
find "$TARGET_DIR" -type d -name '@eaDir' -exec echo '{}' \;
|
|
|
|
# 4. Remove any existing @eaDir directories
|
|
echo "=== Removing existing @eaDir directories ==="
|
|
# Drop indexer sidecars first (often root-owned — passwordless sudo helps)
|
|
if command -v sudo >/dev/null 2>&1; then
|
|
sudo -n find "$TARGET_DIR" -name 'SYNOINDEX_MEDIA_INFO' \( -type f -o -type d \) -exec rm -rf '{}' \; 2>/dev/null || true
|
|
fi
|
|
find "$TARGET_DIR" -name 'SYNOINDEX_MEDIA_INFO' \( -type f -o -type d \) -exec chmod -R u+w '{}' \; 2>/dev/null || true
|
|
find "$TARGET_DIR" -name 'SYNOINDEX_MEDIA_INFO' \( -type f -o -type d \) -exec rm -rf '{}' \; 2>/dev/null || true
|
|
# First make them writable so we can remove them
|
|
find "$TARGET_DIR" -type d -name '@eaDir' -exec chmod -R 755 '{}' \; 2>/dev/null || true
|
|
find "$TARGET_DIR" -path '*/@eaDir/*' -type f -exec chmod 644 '{}' \; 2>/dev/null || true
|
|
# Now remove them (2>/dev/null: races when parents disappear mid-find)
|
|
find "$TARGET_DIR" -type d -name '@eaDir' -exec rm -rf '{}' \; 2>/dev/null || true
|
|
|
|
# 5. Promote every .../eaDir_tmp -> .../@eaDir (thumbgen writes eaDir_tmp next to each video folder, not only TARGET_DIR/eaDir_tmp)
|
|
echo "=== Installing custom thumbnails ==="
|
|
INSTALL_ANY=0
|
|
while IFS= read -r -d '' EADIR_TMP; do
|
|
INSTALL_ANY=1
|
|
promote_one_eadir_tmp "$EADIR_TMP"
|
|
done < <(find "$TARGET_DIR" -type d -name 'eaDir_tmp' -print0)
|
|
if [ "$INSTALL_ANY" -eq 0 ]; then
|
|
echo " -> No eaDir_tmp under $TARGET_DIR; skipping install step"
|
|
fi
|
|
echo "=== Removing any leftover eaDir_tmp directories ==="
|
|
find "$TARGET_DIR" -type d -name 'eaDir_tmp' -exec rm -rf '{}' \; 2>/dev/null || true
|
|
|
|
# 6. Protect custom thumbnails with read-only permissions
|
|
echo "=== Adding indexing exclusion hints ==="
|
|
find "$TARGET_DIR" -type d -name '@eaDir' -exec sh -c 'touch "$1/.noindex" 2>/dev/null || true' _ {} \; 2>/dev/null || true
|
|
|
|
# 7. Protect custom thumbnails with read-only permissions (after .noindex)
|
|
echo "=== Protecting custom thumbnails ==="
|
|
find "$TARGET_DIR" -type d -name '@eaDir' -exec chmod 555 '{}' \; 2>/dev/null || true
|
|
find "$TARGET_DIR" -path '*/@eaDir/*' -type f -exec chmod 444 '{}' \; 2>/dev/null || true
|
|
|
|
echo "=== Cleanup complete! ==="
|
|
echo "Restarting indexing services (best effort)..."
|
|
if [ -n "$SYNOCTL" ]; then
|
|
"$SYNOCTL" --start synoindexd 2>/dev/null || true
|
|
"$SYNOCTL" --start pkgctl-SynoFinder 2>/dev/null || true
|
|
elif command -v systemctl >/dev/null 2>&1; then
|
|
for u in synoindexd pkgctl-SynoFinder; do
|
|
sudo -n systemctl start "$u" 2>/dev/null || systemctl start "$u" 2>/dev/null || true
|
|
done
|
|
fi
|
|
echo "Note: If indexing was stopped and needs restarting, use DSM UI or: sudo systemctl restart synoindexd" |