ro
Think of your sequentially numbered files as a deck of cards. ro moves a
card to any slot and the cards between the old and new positions slide to
fill the gap. Or spread the deck: push a card and everything above it up to
leave space for new files to land nearby.
pip install ro-cli
Usage
ro FILE N [options]
Move FILE to slot N, shifting siblings to keep the sequence dense.
| Flag | Description |
|---|---|
-m, --move |
Block-shift FILE and everything above by N − current (opens a gap when up, closes one when down) |
-s, --suffix |
Force suffix mode (name_NNN.ext). By default the position is auto-detected from FILE |
-z W, --zpad W |
Digit-field width. By default auto-detected from FILE |
-d, --dry-run |
Print the plan without executing |
-n, --no-git |
Use shutil.move even inside a git repo |
Exit codes: 0 success · 1 user error · 2 internal failure / partial rollback.
Examples
# Move migration 005 back to slot 3. Files 003 and 004 shift up one each.
ro 005_create_users.sql 3
# Preview the plan first
ro 005_create_users.sql 3 --dry-run
# Create space at slots 4–6 before adding three new migrations
ro 003_create_users.sql 7 --move
# Changed your mind. Pull 007 back down to 3 and close the gap.
ro 007_create_users.sql 3 --move
# DAW stems numbered at the end. Suffix detected automatically.
ro kick_005.wav 2
# Five-digit sequences. Zpad detected automatically from the filename.
ro 00005_chapter.md 2
The two primitives
Slide (ro FILE N) moves FILE to position N. Every file between
the old and new slot shifts one step to close the gap. The deck stays dense,
no holes.
Block-shift (ro FILE N -m) moves FILE and every file above it as a
block by N − current. Moving up opens a gap below for new files. Moving
down closes a gap that was previously opened. If the destination range is
already occupied, ro errors out. Use slide instead.
How it works
- Builds the complete rename plan before touching any file.
- Preflights the directory and the plan. Any of these halts before any
filesystem change:
- A destination filename already on disk.
- A destination index already occupied by a file the plan isn't moving.
- A sibling file that looks numbered but uses a different mode or
digit width than
FILE. - A duplicate index in the directory.
- Executes atomically: moves the source to a temp name first, shifts siblings, then moves the temp to the final destination.
- Rolls back all completed moves on any failure.
- Prefers
git mvinside a git repository to keep history. Silently falls back toshutil.movefor untracked files. Use-nto opt out entirely. - Non-numeric files (READMEs, configs, etc.) in the directory produce a warning and are skipped. They don't block the operation.
Naming conventions supported
Both number position (prefix vs. suffix) and digit width are detected
automatically from FILE. The -s and -z flags are override escape
hatches for ambiguous cases.
| Convention | Example | Auto-detected |
|---|---|---|
| Numeric prefix | 003_create_users.sql |
yes |
| Numeric suffix | kick_003.wav |
yes |
| Wide zero-pad | 00005_chapter.md |
yes (zpad=5) |
Full-regex extraction was considered and rejected as too much surface area. Prefix and suffix cover the vast majority of real-world patterns, and either is detected on sight.
Who it's for
Anyone who keeps order visible in the filename rather than hidden in metadata, timestamps, or a graph:
- Database migrations in projects that still number them (CodeIgniter, legacy Rails)
- Static-site numbered posts (Jekyll, Hugo)
- Documentation chapters and numbered slides
- DAW stem files
- Zettelkasten numbered notes
- Any directory where humans encode order with leading or trailing numbers
Why numbered sequences
Timestamp prefixes and linked-list migration graphs (Alembic, Flyway) exist to avoid the merge-time friction of dense sequences. Two branches both want slot 017. The usual fix is to abandon the sequence model, which moves the ordering decision somewhere the human doing the merge can't see.
Keeping the sequence puts ordering right in the filename, where every
tool and every reader sees it the same way. The cost is renames when
the sequence shifts, and ro eats that cost: build the plan, verify
no collisions, execute atomically, keep git history. Human decides the
order. ro makes the arithmetic correct.
Prior art
perl rename, util-linux rename, mmv, and vidir all handle
arbitrary rename patterns, but none implement dense-sequence
reordering. That's why the ecosystems that needed it most routed
around the problem rather than solving it.
License
Metadata
Release files for ro-cli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ro_cli-0.1.0.tar.gz | 11.6 kB | Without provenance | Details for ro_cli-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ro_cli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for ro_cli-0.1.0-py3-none-any.whl |
Total release size: 19.7 kB
Release files / ro_cli-0.1.0.tar.gz
| Download URL | ro_cli-0.1.0.tar.gz |
|---|---|
| Size | 11.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
53ded16ea93be6fbd1379d812241f99378bae77e78866912aade9063cab91f03
|
|
BLAKE2b-256 checksum How to use checksums |
1f2cb73ab40394ce0146e9729250bede623734557ed29ed90e71002d7ea63aab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-httpx/0.27.2
|
Release files / ro_cli-0.1.0-py3-none-any.whl
| Download URL | ro_cli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
90f6d8d34d2b04b451f9de494537e7ac85c6a5a7147de884b4610d7685ee7320
|
|
BLAKE2b-256 checksum How to use checksums |
942a9f53d86dc667fbc0accc26181b5721871c594c2dcbda352801bdbad6516d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-httpx/0.27.2
|
Security for ro-cli 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.