Skip to main content

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 mv inside a git repository to keep history. Silently falls back to shutil.move for untracked files. Use -n to 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

MIT

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)

Source distribution for ro-cli 0.1.0
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)

Table of built distributions (wheels) for ro-cli 0.1.0
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page