Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59dba20c1e | |||
| 76574e2bee |
Binary file not shown.
@@ -7,7 +7,7 @@ A **native Linux** GUI for mass renaming files. Inspired by [Bulk Rename Utility
|
||||
- **GUI** – Structure renames with rule panels; no command line needed.
|
||||
- **Preview** – See “Original → New name” for every file before committing.
|
||||
- **Multiple rules** – Combine rules (order: Replace → Regex → Insert → Remove → Case → Numbering → Episode renumber → Prefix/Suffix). Enable only the rules you need.
|
||||
- **Episode renumbering** – Replace episode numbers (e.g. `S01E05 - Title` → `S01E01 - Title`) while keeping season and title. Start number and zero-padding configurable.
|
||||
- **Episode renumbering** – Replace episode numbers (e.g. `S01E05 - Title` → `S01E01 - Title`) while keeping season and title. Multi-episode files like `S01E05-E06` become `S01E01-E02` (range length preserved). Start, step, and zero-padding configurable.
|
||||
- **Replace / Regex** – Plain text find/replace or full regex with capture groups.
|
||||
- **Insert / Remove** – Insert text at start/end/position; remove text, digits, or first/last N characters.
|
||||
- **Case** – Title Case, UPPER, lower, Sentence case.
|
||||
@@ -62,6 +62,10 @@ Sort order is the current list order (alphabetical by filename). Reorder files i
|
||||
3. Enable **9. CSV mapping**, click **Browse…** and select the CSV.
|
||||
4. Only rows that match a current filename in the folder are renamed; others are unchanged. You can combine with other rules (CSV is applied in rule order).
|
||||
|
||||
## Gear Lever (AppImage updates)
|
||||
|
||||
To have [Gear Lever](https://github.com/mijorus/gearlever) see new releases when we push them and update the AppImage from there, see **[docs/GEARLEVER.md](docs/GEARLEVER.md)** for configuration (custom update URL for Gitea, or static URL).
|
||||
|
||||
## AppImage (distribution)
|
||||
|
||||
To build a portable AppImage:
|
||||
|
||||
@@ -54,6 +54,7 @@ else
|
||||
fi
|
||||
|
||||
echo "=== Building AppImage (requires appimagetool) ==="
|
||||
# Note: appimagetool does not accept plain https URLs for -u; use zsync/gh-releases-zsync per AppImage docs.
|
||||
if command -v appimagetool &>/dev/null; then
|
||||
OUT="${APP_NAME}.AppImage"
|
||||
appimagetool "$APPDIR" "$OUT"
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# Using HSRename with Gear Lever
|
||||
|
||||
[Gear Lever](https://github.com/mijorus/gearlever) can manage and update the HSRename AppImage. Because releases are hosted on **Gitea** (not GitHub), use one of the options below.
|
||||
|
||||
## Option 1: Custom update URL (recommended to try first)
|
||||
|
||||
Gitea uses the same release path style as GitHub:
|
||||
`/owner/repo/releases/download/{tag}/{filename}`
|
||||
|
||||
1. Open **Gear Lever** and add the HSRename AppImage (drag & drop or **Add**).
|
||||
2. Select the HSRename entry and open **Update** / **Custom update URL** (or the equivalent in your Gear Lever version).
|
||||
3. Try this URL pattern (with a wildcard for the tag):
|
||||
```
|
||||
http://brassnet.ddns.net:33983/Dawnsorrow/HS-Rename/releases/download/*/HSRename.AppImage
|
||||
```
|
||||
4. If Gear Lever accepts it (e.g. field turns green or validates), it may use the Gitea releases page to resolve the latest tag and offer updates when you push new releases.
|
||||
5. Use **Check for updates** / **List updates** to see if it detects new versions.
|
||||
|
||||
If your Gear Lever only supports GitHub-style URLs and rejects this, use Option 2.
|
||||
|
||||
## Option 2: Static URL (manual update link)
|
||||
|
||||
If the wildcard URL does not work:
|
||||
|
||||
1. In Gear Lever, add HSRename and set **Update** to **Static URL**.
|
||||
2. Paste the **direct download URL** of the current release, for example:
|
||||
- **v1.0.1:**
|
||||
`http://brassnet.ddns.net:33983/Dawnsorrow/HS-Rename/releases/download/v1.0.1/HSRename.AppImage`
|
||||
3. When a new version is released (e.g. v1.0.2), open the [releases page](http://brassnet.ddns.net:33983/Dawnsorrow/HS-Rename/releases), open the new release, right‑click **HSRename.AppImage** → **Copy link address**, then in Gear Lever set the Static URL to that new link and run **Update**.
|
||||
|
||||
So: Gear Lever will only “see” updates if you change the Static URL to the new release’s download link when you want to update.
|
||||
|
||||
## Option 3: CLI (if you use Gear Lever from the terminal)
|
||||
|
||||
After adding the AppImage in Gear Lever, you can set the update URL from the command line:
|
||||
|
||||
```bash
|
||||
# Set custom update URL (try the wildcard pattern)
|
||||
gearlever --set-update-url /path/to/HSRename.AppImage "http://brassnet.ddns.net:33983/Dawnsorrow/HS-Rename/releases/download/*/HSRename.AppImage"
|
||||
|
||||
# Check for updates
|
||||
gearlever --list-updates
|
||||
|
||||
# Apply update
|
||||
gearlever --update /path/to/HSRename.AppImage
|
||||
```
|
||||
|
||||
Replace `/path/to/HSRename.AppImage` with the actual path where Gear Lever stores the AppImage.
|
||||
|
||||
## Release download URL pattern
|
||||
|
||||
For any release tag `vX.Y.Z`, the direct download URL is:
|
||||
|
||||
```
|
||||
http://brassnet.ddns.net:33983/Dawnsorrow/HS-Rename/releases/download/vX.Y.Z/HSRename.AppImage
|
||||
```
|
||||
|
||||
So when we push a new release (e.g. v1.0.2), that new tag’s URL is what Gear Lever needs (either via the wildcard in Option 1 or by pasting the new URL in Option 2).
|
||||
+33
-7
@@ -201,14 +201,14 @@ class NumberingRule(Rule):
|
||||
return stem, ext
|
||||
|
||||
|
||||
# Episode renumber: match SxxExx or similar, replace episode number only, keep title
|
||||
# Episode renumber: match SxxExx or SxxExx-Eyy, replace episode block; keep title
|
||||
@dataclass
|
||||
class EpisodeRenumberRule(Rule):
|
||||
start: int = 1
|
||||
step: int = 1
|
||||
padding: int = 2
|
||||
# Pattern: group 1 = prefix (e.g. "S01E"), group 2 = episode digits, group 3 = rest (title)
|
||||
pattern: str = r"(.*?[Ss]\d+[Ee])(\d+)(.*)"
|
||||
# Group 1 = prefix (e.g. "S01E"), 2 = first ep digits, 3 = full "-E06" or None, 4 = second ep if range, 5 = rest (title)
|
||||
pattern: str = r"(.*?[Ss]\d+[Ee])(\d+)(-[Ee](\d+))?(.*)"
|
||||
|
||||
def apply(
|
||||
self,
|
||||
@@ -224,10 +224,36 @@ class EpisodeRenumberRule(Rule):
|
||||
return stem, ext
|
||||
if not m:
|
||||
return stem, ext
|
||||
prefix, _old_ep, rest = m.group(1), m.group(2), m.group(3)
|
||||
ep_num = self.start + index * self.step
|
||||
ep_str = str(ep_num).zfill(max(1, self.padding))
|
||||
new_stem = f"{prefix}{ep_str}{rest}"
|
||||
prefix, old_first_s, range_dash_e, old_second_s, rest = (
|
||||
m.group(1),
|
||||
m.group(2),
|
||||
m.group(3),
|
||||
m.group(4),
|
||||
m.group(5),
|
||||
)
|
||||
try:
|
||||
old_first = int(old_first_s)
|
||||
except ValueError:
|
||||
return stem, ext
|
||||
span = 1
|
||||
if old_second_s is not None:
|
||||
try:
|
||||
old_second = int(old_second_s)
|
||||
except ValueError:
|
||||
return stem, ext
|
||||
span = old_second - old_first + 1
|
||||
if span < 1:
|
||||
span = 1
|
||||
ep_new_first = self.start + index * self.step
|
||||
pad = max(1, self.padding)
|
||||
e1 = str(ep_new_first).zfill(pad)
|
||||
if span <= 1:
|
||||
new_stem = f"{prefix}{e1}{rest}"
|
||||
else:
|
||||
ep_new_last = ep_new_first + span - 1
|
||||
e2 = str(ep_new_last).zfill(pad)
|
||||
# Match common style: S01E01-E02 (second block uses E again)
|
||||
new_stem = f"{prefix}{e1}-E{e2}{rest}"
|
||||
return new_stem, ext
|
||||
|
||||
|
||||
|
||||
+4
-1
@@ -285,7 +285,10 @@ class EpisodeRenumberRuleWidget(QWidget):
|
||||
layout.addRow("First episode number:", self.start)
|
||||
layout.addRow("Step:", self.step)
|
||||
layout.addRow("Zero-pad width:", self.padding)
|
||||
info = QLabel("Matches patterns like S01E05 - Title or Show 1x03 - Title. Episode number is replaced; title is kept.")
|
||||
info = QLabel(
|
||||
"Matches S01E05 - Title (single) or S01E05-E06 - Title (two-part). "
|
||||
"Ranges keep their length: S01E01-E02, S01E03-E04, … Order follows the file list / table sort."
|
||||
)
|
||||
info.setWordWrap(True)
|
||||
layout.addRow(info)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user