From 74b210a7029d287bd5f6e73cf5cbe8c71f3433b3 Mon Sep 17 00:00:00 2001 From: Laurence Horrocks-Barlow Date: Thu, 21 May 2026 10:33:10 +0100 Subject: [PATCH] Add README, runbook, per-script docs, CHANGELOG and LICENSE. Documents the organise-isos and generate-ventoy-json workflow end-to-end: quick start in the README, full procedure with troubleshooting and recovery in docs/RUNBOOK.md, and reference docs for each script covering parameters, parsing rules, category groupings, and extensibility. Ships a YOLO licence (no warranty) and seeds CHANGELOG.md for the v0.1.0 release. --- CHANGELOG.md | 28 +++++ LICENSE | 18 +++ README.md | 72 +++++++++++ docs/RUNBOOK.md | 223 +++++++++++++++++++++++++++++++++++ docs/directory-layout.md | 96 +++++++++++++++ docs/generate-ventoy-json.md | 146 +++++++++++++++++++++++ docs/organise-isos.md | 135 +++++++++++++++++++++ 7 files changed, 718 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 docs/RUNBOOK.md create mode 100644 docs/directory-layout.md create mode 100644 docs/generate-ventoy-json.md create mode 100644 docs/organise-isos.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..100d643 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,28 @@ +# Changelog + +All notable changes to this project are documented in this file. + +The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). + +## [0.1.0] - 2026-05-21 + +First tagged release. Bundles the existing scripts with a documentation set. + +### Added +- `organise-isos.ps1` — filename-driven sorter that moves ISOs into + `iso-library////`. Covers Windows, RHEL family, Fedora + family, SUSE, Debian/Ubuntu and derivatives, Arch family, Gentoo, Slackware, + independent Linux distros, hypervisors, BSDs, Solaris/illumos, exotic OSes, + and rescue tools. +- `generate-ventoy-json.ps1` — generates a categorised `ventoy.json` menu + from the sorted tree, with curated display names and per-family submenus. +- `README.md` — project overview and quick start. +- `docs/RUNBOOK.md` — end-to-end build/refresh procedure with troubleshooting + and recovery sections. +- `docs/organise-isos.md` — parameter reference, parsing rules, extensibility + guide. +- `docs/generate-ventoy-json.md` — parameter reference, category groupings, + menu output shape. +- `docs/directory-layout.md` — on-disk structure for the local working copy + and the Ventoy USB. +- `LICENSE` — YOLO licence, no warranty. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8ded57d --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +YOLO LICENSE +============ + +Copyright (c) 2026 Laurence Horrocks-Barlow + +Do whatever you want with this software. Use it, fork it, sell it, set it on +fire, print it out and use it as wallpaper. No attribution required, no +restrictions, no obligations. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +If things blow up: you keep both pieces. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3bb90c7 --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# ventoy-extras + +PowerShell helpers for keeping a tidy [Ventoy](https://www.ventoy.net/) USB +drive. Drops a pile of randomly-named ISOs into a sensible directory tree, then +generates a categorised `ventoy.json` so the boot menu groups them by OS family +instead of vomiting one flat list. + +Two scripts, no dependencies beyond Windows PowerShell 5.1 (or PowerShell 7+). + +## Scripts + +| Script | Purpose | +| --- | --- | +| [`organise-isos.ps1`](organise-isos.ps1) | Parse ISO filenames, infer `os/version/arch`, move into `iso-library\\\\` | +| [`generate-ventoy-json.ps1`](generate-ventoy-json.ps1) | Walk that tree and emit `ventoy.json` with a per-family submenu structure | + +## Quick start + +```powershell +# 1. Drop all your downloaded ISOs into a working directory, then: +.\organise-isos.ps1 -SourceDir .\downloads -DestDir .\iso-library -DryRun +# Review the planned moves, then re-run without -DryRun +.\organise-isos.ps1 -SourceDir .\downloads -DestDir .\iso-library + +# 2. Generate the ventoy menu config: +.\generate-ventoy-json.ps1 -IsoRoot .\iso-library -OutFile .\ventoy.json + +# 3. Copy iso-library\ to the root of your Ventoy USB, and copy +# ventoy.json into the ventoy\ folder on that same drive. +``` + +That's the whole workflow. See [`docs/RUNBOOK.md`](docs/RUNBOOK.md) for the +detailed operational walkthrough, and the per-script docs for the gory bits. + +## Documentation + +- [`docs/RUNBOOK.md`](docs/RUNBOOK.md) — end-to-end procedure, troubleshooting, recovery +- [`docs/organise-isos.md`](docs/organise-isos.md) — parameters, naming rules, OS detection map +- [`docs/generate-ventoy-json.md`](docs/generate-ventoy-json.md) — parameters, category groupings, menu layout +- [`docs/directory-layout.md`](docs/directory-layout.md) — what the on-disk tree looks like and why + +## Directory layout produced + +``` +iso-library\ + ubuntu\ + 24.04\ + x86_64\ + ubuntu-24.04.1-desktop-amd64.iso + debian\ + 12\ + x86_64\ + debian-12.5.0-amd64-netinst.iso + rocky\ + 9\ + aarch64\ + Rocky-9.3-aarch64-minimal.iso + ... +``` + +Three levels: OS slug, version, architecture. Ventoy follows directories +transparently, so the same tree is what ends up on the USB. + +## Requirements + +- Windows PowerShell 5.1 or PowerShell 7+ +- A Ventoy USB drive (set up separately — see [ventoy.net](https://www.ventoy.net/)) +- Enough disk space to hold your ISO collection twice during reorganisation + +## License + +[YOLO LICENSE](LICENSE) — do whatever you want with it, no warranty, things may blow up. diff --git a/docs/RUNBOOK.md b/docs/RUNBOOK.md new file mode 100644 index 0000000..01b7ae3 --- /dev/null +++ b/docs/RUNBOOK.md @@ -0,0 +1,223 @@ +# Runbook: Building and refreshing a Ventoy USB + +End-to-end procedure for taking a pile of downloaded ISOs and turning them into +a categorised Ventoy boot stick. Designed to be safe to run repeatedly — adding +new ISOs later is the same flow. + +## Audience and assumptions + +- You already have a Ventoy-formatted USB drive (Ventoy installed via + `Ventoy2Disk` or similar). If not, do that first at + [ventoy.net](https://www.ventoy.net/) — these scripts only manage the + payload, not the bootloader. +- You're on Windows with PowerShell 5.1+ or PowerShell 7+. +- You have all the ISOs you want to deploy in a single staging directory. + +## Drive layout this runbook produces + +Two locations on the Ventoy USB matter: + +| Path on USB | What it holds | +| --- | --- | +| `\iso-library\\\\*.iso` | The actual ISO payload | +| `\ventoy\ventoy.json` | The menu definition Ventoy reads at boot | + +Ventoy itself only requires that ISOs exist somewhere on the data partition. +The `iso-library\` tree and the `ventoy.json` menu definition are layered on +top to give a navigable boot menu. + +--- + +## Procedure + +### Step 1 — Stage the ISOs + +Put every ISO you want into one directory. Filenames don't need to be +"clean"; the parser handles vendor-supplied names like +`Win11_24H2_English_x64.iso`, `ubuntu-24.04.1-desktop-amd64.iso`, +`Rocky-9.3-x86_64-minimal.iso`, etc. + +```powershell +# Example staging area: +dir D:\iso-staging\ +# Win11_24H2_English_x64.iso +# ubuntu-24.04.1-desktop-amd64.iso +# debian-12.5.0-amd64-netinst.iso +# Rocky-9.3-x86_64-minimal.iso +# clonezilla-live-3.1.2-22-amd64.iso +``` + +### Step 2 — Dry-run the organiser + +Always start with `-DryRun` to confirm the parser inferred the right +`os/version/arch` for each file. Nothing is moved. + +```powershell +cd D:\Projects\own\forgejo\ventoy-extras +.\organise-isos.ps1 -SourceDir D:\iso-staging -DestDir D:\iso-library -DryRun +``` + +Output shows the planned target for every ISO. Look for anything that +parsed as `unknown` or landed in a surprising slot — those are the cases +to triage before committing to a move. + +### Step 3 — Run the organiser for real + +Once the dry-run looks right: + +```powershell +.\organise-isos.ps1 -SourceDir D:\iso-staging -DestDir D:\iso-library +``` + +This **moves** (not copies) ISOs into `iso-library\\\\`. +Source directory will be left empty (modulo non-ISO files). If you want +copies kept, copy the staging directory aside first. + +### Step 4 — Generate `ventoy.json` + +```powershell +.\generate-ventoy-json.ps1 -IsoRoot D:\iso-library -OutFile D:\ventoy.json +``` + +The script prints the menu tree it built. Skim it to confirm sensible +category groupings and labels. + +### Step 5 — Deploy to the USB + +Plug in the Ventoy USB and note its drive letter (assume `E:` below). + +```powershell +# Mirror the iso-library tree onto the stick. Robocopy is safest because +# it handles long paths and resumes gracefully. +robocopy D:\iso-library E:\iso-library /MIR /R:1 /W:1 + +# Drop the menu file into the ventoy\ folder on the stick. +Copy-Item D:\ventoy.json E:\ventoy\ventoy.json -Force +``` + +`E:\ventoy\` should already exist — Ventoy creates it when it installs the +bootloader. If it doesn't, the Ventoy install is incomplete. + +### Step 6 — Verify the boot menu + +Boot a machine (or a VM with USB passthrough) from the stick. The Ventoy +menu should show category submenus rather than one flat list. If categories +are missing, see [Troubleshooting](#troubleshooting). + +--- + +## Adding ISOs later + +You don't have to redo the whole flow. To add a single new ISO: + +```powershell +# Option A — let the organiser handle it +.\organise-isos.ps1 -SourceDir C:\downloads -DestDir D:\iso-library +.\generate-ventoy-json.ps1 -IsoRoot D:\iso-library -OutFile D:\ventoy.json +robocopy D:\iso-library E:\iso-library /MIR /R:1 /W:1 +Copy-Item D:\ventoy.json E:\ventoy\ventoy.json -Force + +# Option B — manually drop the ISO into the right tree, then just regenerate +Copy-Item C:\downloads\new.iso D:\iso-library\foo\1.2\x86_64\ +.\generate-ventoy-json.ps1 -IsoRoot D:\iso-library -OutFile D:\ventoy.json +Copy-Item D:\ventoy.json E:\ventoy\ventoy.json -Force +``` + +`robocopy /MIR` will also **remove** ISOs from the stick that no longer exist +in the local library — useful for retiring old versions, dangerous if your +local copy is incomplete. Skip `/MIR` and use `/E` instead if you only want +additive sync. + +--- + +## Troubleshooting + +### An ISO landed in `unknown\unknown\noarch\` + +The filename didn't match any pattern in the OS map. Fix one of: + +1. Rename the ISO to start with a recognised slug + (e.g. `myweirdspin-2024.iso` becomes `arch-2024-myweirdspin.iso`). +2. Add a pattern to `$osNormMap` in + [`organise-isos.ps1`](../organise-isos.ps1) — the regex matches against + the lowercased first token of the cleaned filename. + +After fixing, move the file back to staging and re-run. + +### Version parsed as `unknown` + +Filename didn't contain a recognisable version. Either rename the file to +include a `\d+\.\d+` style version, or move it manually into the right +`` folder and regenerate. + +### Wrong architecture detected + +`organise-isos.ps1` checks arch tokens in priority order (see +[`docs/organise-isos.md`](organise-isos.md)). If a token in the filename +collides (e.g. a date that looks like an arch), rename the file or move +it manually. Common gotcha: macOS-style x64 in the version string. + +### Ventoy boots but shows the old flat list + +`ventoy.json` is in the wrong place. It must be at the **root** of the +Ventoy data partition's `ventoy\` folder, exactly: `\ventoy\ventoy.json`. +Not `\ventoy\config\`, not anywhere else. + +### Ventoy reports JSON parse error on boot + +Open `ventoy.json` in any editor and confirm it's valid JSON. The +generator writes UTF-8 with no BOM, which Ventoy accepts. If you've +hand-edited it, double-check for trailing commas (not valid JSON) or +unbalanced brackets. + +### A category I want is missing + +Add the slug to `$categoryMap` in +[`generate-ventoy-json.ps1`](../generate-ventoy-json.ps1), then re-run. +Unmapped slugs land in `Other`. + +### `Access denied` when moving ISOs + +The source ISO is probably open in another process (mount, antivirus +scan, browser download still finalising). Close it and retry. If on a +removable drive, eject and reattach. + +--- + +## Recovery + +### "I ran organise-isos and now my ISOs are scattered, how do I get them back?" + +The organiser only moves files into `\\\\`. To +collapse everything back into one directory: + +```powershell +Get-ChildItem -Path D:\iso-library -Recurse -Filter *.iso | + Move-Item -Destination D:\iso-staging +``` + +Then delete the empty tree: + +```powershell +Get-ChildItem -Path D:\iso-library -Recurse -Directory | + Where-Object { -not (Get-ChildItem $_.FullName -Recurse -File) } | + Remove-Item -Recurse +``` + +### "My USB is borked" + +These scripts don't touch the Ventoy bootloader — only the data partition +content. To recover the bootloader, reinstall Ventoy with `Ventoy2Disk.exe` +using the **upgrade** option (preserves the data partition) or the +**install** option (wipes it). If you only modified `ventoy.json` and the +boot menu now errors, just delete `\ventoy\ventoy.json` from the stick; +Ventoy falls back to its default flat menu. + +--- + +## Smoke test before deploying + +Want to confirm the menu before copying to a real USB? Mount the +`iso-library` and `ventoy.json` into a VM with Ventoy installed, or use +[VBoxVentoy](https://www.ventoy.net/en/doc_vbox.html) to boot from a +VirtualBox USB device. Saves wear on physical sticks. diff --git a/docs/directory-layout.md b/docs/directory-layout.md new file mode 100644 index 0000000..5c0f723 --- /dev/null +++ b/docs/directory-layout.md @@ -0,0 +1,96 @@ +# Directory layout + +A description of the on-disk shape these scripts work with — both the local +working copy and what ends up on the Ventoy USB. + +## Local working copy + +``` +ventoy-extras/ # this repo +├─ organise-isos.ps1 +├─ generate-ventoy-json.ps1 +├─ ventoy.json # generated, gitignored — your menu +├─ iso-library/ # generated, gitignored — your ISOs +│ ├─ ubuntu/ +│ │ └─ 24.04/ +│ │ └─ x86_64/ +│ │ └─ ubuntu-24.04.1-desktop-amd64.iso +│ ├─ debian/ +│ │ └─ 12/ +│ │ └─ x86_64/ +│ │ └─ debian-12.5.0-amd64-netinst.iso +│ ├─ rocky/ +│ │ └─ 9.3/ +│ │ ├─ x86_64/ +│ │ │ └─ Rocky-9.3-x86_64-minimal.iso +│ │ └─ aarch64/ +│ │ └─ Rocky-9.3-aarch64-minimal.iso +│ ├─ proxmox-ve/ +│ │ └─ 8.2/ +│ │ └─ noarch/ +│ │ └─ proxmox-ve_8.2-1.iso +│ └─ ... +└─ docs/ +``` + +You can keep `iso-library/` and `ventoy.json` anywhere — pass `-IsoRoot` +and `-OutFile` to point at them. Keeping them outside the repo is the +sensible default for non-trivial ISO collections. + +## On the Ventoy USB + +``` +E:\ # Ventoy data partition root +├─ ventoy\ +│ ├─ ventoy.json # copied from the generated file +│ ├─ theme\ # optional, not managed by these scripts +│ └─ ... # other Ventoy config +├─ iso-library\ +│ ├─ ubuntu\ +│ │ └─ 24.04\ +│ │ └─ x86_64\ +│ │ └─ ubuntu-24.04.1-desktop-amd64.iso +│ └─ ... +└─ (anything else you want on the stick) +``` + +Ventoy treats the data partition as a regular FAT/exFAT/NTFS filesystem. +The bootloader lives on a separate hidden ESP partition that these scripts +do not touch. + +## Why three levels (`os/version/arch`) + +- **`os/`** — keeps the same OS together regardless of version churn. Easier + to clean up when retiring an EOL distro. +- **`version/`** — lets you have multiple versions of the same OS without + filename collisions, and gives Ventoy a clean per-version label. +- **`arch/`** — multi-arch ISOs (typically x86_64 + aarch64 for RHEL family, + Debian, Ubuntu) sort cleanly side by side. + +When arch isn't applicable (hypervisor appliances, BSD distros that ship +multi-arch in one image), the slot becomes `noarch\` and the generator omits +the `[]` suffix from menu labels. + +## Path constraints + +- **Forward vs backslash**: the local Windows paths use `\`. `ventoy.json` + paths use `/` (Ventoy is essentially Linux-bootstrapped and expects POSIX + paths). The generator handles the translation. +- **Leading slash**: `ventoy.json` paths start with `/` and are rooted at + the **Ventoy data partition root**, not the filesystem root. +- **Long paths**: deeply-nested distros (`opensuse-tumbleweed/...`) plus + long ISO filenames can exceed 260 chars on Windows. PowerShell 7+ handles + this transparently; on 5.1 you may need `\\?\` prefixes if you hit it. + Robocopy handles long paths regardless of PS version. + +## Gitignore recommendation + +A `.gitignore` for this repo (not yet committed): + +``` +iso-library/ +ventoy.json +*.iso +``` + +ISOs are large and frequently rotated. Don't commit them. diff --git a/docs/generate-ventoy-json.md b/docs/generate-ventoy-json.md new file mode 100644 index 0000000..c443acb --- /dev/null +++ b/docs/generate-ventoy-json.md @@ -0,0 +1,146 @@ +# `generate-ventoy-json.ps1` + +Walks an `iso-library` directory tree and emits a `ventoy.json` with +per-category submenus. Output is UTF-8, no BOM, ready to drop into +`\ventoy\ventoy.json` on the Ventoy USB. + +## Parameters + +| Parameter | Default | Description | +| --- | --- | --- | +| `-IsoRoot` | `.\iso-library` | Root of the ISO tree to scan (recursively, for `*.iso`). | +| `-OutFile` | `.\ventoy.json` | Where to write the generated JSON. | +| `-VentoyDrive` | `E` | Cosmetic — currently unused at runtime; kept for forward compat. | + +## Expected input tree + +``` +\ + \ + \ + \ + *.iso +``` + +This is exactly what [`organise-isos.ps1`](organise-isos.md) produces. +Files that don't fit this layout still get included, but with a best-effort +fallback: + +- 3 path segments deep → arch defaults to `noarch`. +- < 3 segments → `os` and `version` both default to `unknown`. + +## Output structure + +Each top-level entry in `ventoy.json` is a category submenu, containing one +entry per ISO: + +```json +{ + "menu_alias": [ + { + "name": "Ubuntu Family", + "image": [ + { "image": "/ubuntu/24.04/x86_64/ubuntu-24.04.1-desktop-amd64.iso", + "menu_alias": "Ubuntu 24.04 [x86_64]" }, + { "image": "/lubuntu/24.04/x86_64/lubuntu-24.04-desktop-amd64.iso", + "menu_alias": "Lubuntu 24.04 [x86_64]" } + ] + }, + { + "name": "Rescue & Tools", + "image": [ + { "image": "/clonezilla/3.1/x86_64/clonezilla-live-3.1.2-22-amd64.iso", + "menu_alias": "Clonezilla 3.1 [x86_64]" } + ] + } + ] +} +``` + +## Menu labels + +For each ISO, the label is built as: + +``` + [ []] +``` + +Where: + +- `` is looked up in `$displayNames` (e.g. `ubuntu` → `Ubuntu`, + `proxmox-ve` → `Proxmox VE`). Unmapped slugs are title-cased as a fallback. +- The arch suffix `[]` is omitted when arch is `noarch`. + +Examples: `Ubuntu 24.04 [x86_64]`, `Proxmox VE 8.2`, `Memtest86+ 6.20 [x86_64]`. + +## Category groupings + +Slugs are mapped to category names via `$categoryMap`: + +| Category | Slugs included | +| --- | --- | +| Windows | `windows`, `windows-server`, `ms-dos`, `reactos` | +| RHEL Family | `rhel`, `centos`, `rocky`, `almalinux`, `oraclelinux`, `scientific`, `eurolinux`, `navylinux` | +| Fedora Family | `fedora`, `qubes`, `coreos` | +| SUSE Family | `opensuse*`, `sles`, `geckolinux` | +| Debian Family | `debian`, `raspios`, `armbian`, `devuan`, `mx`, `antix`, `deepin`, `pureos`, `grml`, `lmde` | +| Ubuntu Family | `ubuntu*`, `lubuntu`, `kubuntu`, `xubuntu`, `linuxmint`, `pop_os`, `elementary`, `zorin` | +| Arch Family | `arch`, `manjaro`, `endeavouros`, `garuda`, `artix`, `cachyos`, `arcolinux` | +| Gentoo Family | `gentoo`, `funtoo`, `calculate` | +| Slackware Family | `slackware`, `salix`, `porteus` | +| Independent Linux | `void`, `nixos`, `alpine`, `solus`, `clearlinux`, `flatcar` | +| Security | `kali`, `parrot`, `backbox`, `tails`, `whonix`, `blackarch` | +| Network & Firewall | `pfsense`, `opnsense`, `ipfire`, `vyos`, `openwrt`, `ddwrt` | +| Virtualisation | `proxmox-*`, `esxi`, `vsphere`, `xcp-ng`, `xenserver`, `harvester` | +| BSD Family | `freebsd`, `openbsd`, `netbsd`, `dragonflybsd`, `truenas*`, `ghostbsd` | +| Solaris & illumos | `openindiana`, `omnios`, `smartos`, `solaris` | +| Media | `libreelec`, `osmc` | +| Exotic | `haiku`, `freedos`, `reactos` | +| Rescue & Tools | `clonezilla`, `systemrescue`, `gparted`, `memtest`, `memtest86`, `rescuezilla`, `hirens`, `winpe`, `dban`, `ubcd`, vendor rescue disks | +| Other | anything unmapped — sorted alphabetically at the end | + +Matching is exact-first, then prefix. So `opensuse-leap` matches the exact +`opensuse-leap` entry if present, otherwise falls through to the `opensuse` +prefix. + +Category order in the output menu is fixed (see `$categoryOrder` in the +script). Unlisted categories — including any new ones you add — append +alphabetically after the predefined order. + +## Adding a category + +Edit [`generate-ventoy-json.ps1`](../generate-ventoy-json.ps1): + +```powershell +$categoryMap = [ordered]@{ + # ...existing... + 'mycoolos' = 'Hobbyist OSes' # new category name appears as-is in the menu +} + +# Optional — place it explicitly in the menu order: +$categoryOrder = @( + 'Windows', + # ... + 'Hobbyist OSes', + # ... +) +``` + +## Output details + +- **Encoding**: UTF-8 without BOM. Ventoy accepts this. +- **Indentation**: `ConvertTo-Json -Depth 10` default formatting. +- **Path separators**: forward slashes, leading `/`. Ventoy paths are + rooted at the Ventoy data partition root, not at filesystem root. + +## Exit codes + +- `0` — always. The script prints to stderr but does not exit non-zero + on parsing edge cases; "unknown" categories are silently bucketed into + `Other`. + +## Idempotency + +Pure function of the directory tree. Re-running over the same tree always +produces byte-identical output (modulo line endings if you edited the +script). Safe to run on every Ventoy refresh. diff --git a/docs/organise-isos.md b/docs/organise-isos.md new file mode 100644 index 0000000..100e59c --- /dev/null +++ b/docs/organise-isos.md @@ -0,0 +1,135 @@ +# `organise-isos.ps1` + +Parses ISO filenames, infers `os`, `version`, and `arch`, and moves each file +into `\\\\`. Pure filename parsing — the ISO +itself is never opened. + +## Parameters + +| Parameter | Default | Description | +| --- | --- | --- | +| `-SourceDir` | `.` | Directory to scan for `*.iso` files (non-recursive). | +| `-DestDir` | `.\iso-library` | Target root. Subdirectories are created as needed. | +| `-DryRun` | `false` | Print the moves it would make; touch nothing. | + +## What it does + +1. Enumerates `*.iso` directly under `-SourceDir` (does not recurse). +2. For each file, calls `Get-IsoMeta` to derive `os`, `version`, `arch`. +3. Creates `\\\\` if missing. +4. Moves the ISO in. +5. Prints a table of the results. + +## Parsing rules + +### Architecture + +Checked in priority order against the **raw** filename. First match wins: + +| Pattern | Canonical | +| --- | --- | +| `aarch64`, `arm64` | `aarch64` | +| `arm` (not followed by `64`) | `arm` | +| `x86[_-]64`, `amd64`, `_x64`, `64bit` | `x86_64` | +| `x86` (not followed by `_64`), `i[3-6]86`, `32bit` | `x86` | +| `riscv64`, `riscv32` | `riscv64` / `riscv32` | +| `ppc64le`, `ppc64`, `ppc` | matching | +| `s390x`, `mips64`, `mips`, `loong64`, `ia64`, `sparc64`, `alpha` | matching | + +If nothing matches, arch is `noarch`. + +### Edition noise stripping + +Tokens like `live`, `server`, `desktop`, `dvd`, `netinstall`, `workstation`, +`kde`, `gnome`, `xfce`, language codes (`en_us`, `en_gb`, `international`), +release tags (`lts`, `beta`, `rc1`, `sp2`, `u3`), and similar are stripped +**after** the arch check so they don't pollute the OS-name match. See the +`$noisePattern` regex in the script for the full list. + +### OS detection + +The cleaned filename is split on `-_.` and the first token (lowercased) is +matched against `$osNormMap`. First regex match wins. If no first-token match +hits, the first **two** tokens joined with `-` are tried (catches `linux-mint`, +`pop-os`, `ms-dos`). + +If still no match, the first token is sanitised (`[^a-z0-9-]` removed) and +used as-is, producing a slug like `myweirdspin`. + +The map covers Windows, RHEL family, Fedora family, SUSE, Debian/Ubuntu and +derivatives, Arch family, Gentoo family, Slackware, independent Linux (Void, +NixOS, Alpine, etc.), hypervisors (Proxmox, ESXi, XCP-ng), BSD family, +Solaris/illumos, exotic OSes (Haiku, FreeDOS, ReactOS, Plan9), and rescue +tools (Clonezilla, SystemRescue, GParted, Memtest, Hiren's, DBAN, vendor +rescue disks). Full list is in `$osNormMap` in +[`organise-isos.ps1`](../organise-isos.ps1). + +### Version detection + +Checked in this order, first match wins: + +1. **Windows H-series** — `25H2`, `24H2`, etc. on the raw filename. +2. **Full date stamp** — `YYYYMMDD` → year only (so `20240315` → `2024`). +3. **Semver / partial semver** — `\d+\.\d+(\.\d+)?` on the cleaned name. + Three-part versions are truncated to `major.minor` (so `9.3.1` → `9.3`). +4. **Bare integer** — final fallback, captures things like `debian-12-...`. + +If nothing matches, version is `unknown`. + +## Examples + +| Input filename | OS | Version | Arch | +| --- | --- | --- | --- | +| `ubuntu-24.04.1-desktop-amd64.iso` | `ubuntu` | `24.04` | `x86_64` | +| `Win11_24H2_English_x64.iso` | `windows` | `24H2` | `x86_64` | +| `debian-12.5.0-amd64-netinst.iso` | `debian` | `12.5` | `x86_64` | +| `Rocky-9.3-aarch64-minimal.iso` | `rocky` | `9.3` | `aarch64` | +| `archlinux-2024.03.01-x86_64.iso` | `arch` | `2024.03` | `x86_64` | +| `clonezilla-live-3.1.2-22-amd64.iso` | `clonezilla` | `3.1` | `x86_64` | +| `proxmox-ve_8.2-1.iso` | `proxmox-ve` | `8.2` | `noarch` | +| `systemrescue-11.00-amd64.iso` | `systemrescue` | `11` | `x86_64` | + +## Adding support for a new OS + +Edit [`organise-isos.ps1`](../organise-isos.ps1): + +```powershell +$osNormMap = [ordered]@{ + # ...existing entries... + '^mycoolos|^my.cool.os' = 'mycoolos' +} +``` + +Then add a display name and category in +[`generate-ventoy-json.ps1`](../generate-ventoy-json.ps1): + +```powershell +$displayNames = @{ + 'mycoolos' = 'My Cool OS' +} + +$categoryMap = [ordered]@{ + 'mycoolos' = 'Independent Linux' # or any existing/new category +} +``` + +The `$osNormMap` is **ordered** — earlier patterns win, so put more specific +patterns above more general ones (e.g. `^centos.stream` must come before +`^centos`). + +## Exit codes + +- `0` — success (including dry-run). +- `1` — no ISO files found in `-SourceDir`. + +## Idempotency and re-runs + +Safe to re-run. The first time moves all ISOs out of `-SourceDir`; subsequent +runs find nothing to move (because the source directory is empty) and exit +with code 1. If you want to add ISOs later, drop them into the same source +directory and run again. + +The script does **not** detect duplicates. If you move the same ISO twice +from different sources and they parse to the same target slot, the second +move fails with a `Move-Item` error — by design, since silently +overwriting an ISO would be a footgun.