Files
felhom.eu/documentation/audits/media-all-drives-2026-10-14/tools/where.py
T
admin 8395aee4c2
gates / gates (push) Successful in 7m46s
Media all drives, Parts A-C on Tester 1: S1-S3 proven (hardlink with one bind per drive; today's shape copies); R-1014..R-1019 filed
Two test drives enrolled through the dashboard; no test media in any backup tier (A6, three proofs); Tester 1 follows a
credential-free local mirror of the drill catalog (R-992 worked around a third way). The live-fix task may start.
2026-10-14 17:36:50 +02:00

48 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""where.py — S4: where every media file sits, per drive. Run INSIDE the guest (run_in_guest.py where.py).
For each enrolled drive under /mnt/felhom-drives/*/userdata/media: every regular file (hidden temp folders included)
with its size, link count and inode, grouped by top folder (tv, movies, torrents, transmission, ...). Then the pairs
that are ONE file (same device + inode = a hardlink: no extra copy) and the library files that are NOT linked to any
download (link count 1 = a copy, or a download already removed). Stdlib only; reads, never writes.
"""
import collections, glob, os
ROOTS = sorted(glob.glob("/mnt/felhom-drives/*/userdata/media"))
by_ino = collections.defaultdict(list)
total = 0
for root in ROOTS:
drive = root.split("/")[3]
print(f"== drive {drive} ({root})")
for top in sorted(os.listdir(root)):
rows = []
for dp, dn, fn in os.walk(os.path.join(root, top)):
for f in fn:
p = os.path.join(dp, f)
try:
s = os.lstat(p)
except OSError as e:
rows.append(f" ?? {p}: {e}")
continue
if not os.path.isfile(p) or os.path.islink(p):
continue
total += 1
by_ino[(s.st_dev, s.st_ino)].append((drive, top, p, s.st_size, s.st_nlink))
rows.append(f" {s.st_size/1e6:10.1f} MB links={s.st_nlink} inode={s.st_ino:<10} {os.path.relpath(p, root)}")
if rows:
print(f" -- {top}/ ({len(rows)} file(s))")
print("\n".join(rows))
print(f"\n== {total} file(s) on {len(ROOTS)} drive(s)")
print("== ONE FILE, TWO NAMES (hardlink — no extra copy):")
n = 0
for k, v in by_ino.items():
if len(v) > 1:
n += 1
print(f" drive {v[0][0]} inode {k[1]} ({v[0][3]/1e6:.1f} MB): " + " <-> ".join(f"{x[1]}/…/{os.path.basename(x[2])}" for x in v))
print(f" {n} pair(s)")
print("== LIBRARY FILES WITH LINK COUNT 1 (a copy, or its download is gone):")
for k, v in by_ino.items():
for d, top, p, size, nl in v:
if top in ("tv", "movies") and nl == 1:
print(f" drive {d}: {os.path.relpath(p, '/mnt/felhom-drives')} ({size/1e6:.1f} MB)")