| Installation | Usage | Flags | How It Works | Contributing |
moni renames generic files (like image.jpg or download (1).png) into a clean, chronological, fingerprint-based format (YYYYMMDD_HHMMSS_<hash>.ext) without overwriting existing files.
$ moni ~/Downloads
- downloads/image.jpg
+ downloads/20260127_150405_a1b2c3d4e5f6.jpg
- downloads/image (1).jpg
+ downloads/20260127_150405_a1b2c3d4e5f6_1.jpg
Apply these changes? [y/N]: y
Done! Renamed 2 file(s).This is the fastest way — you don't even need to have Go installed on your system. Each release provides archives for Linux, macOS, and Windows on amd64 and arm64, plus a SHA-256 checksums.txt manifest.
- Go to the Releases page.
- Download the archive for your operating system and architecture.
- Extract the
moniexecutable and move it to a directory in your system'sPATH(e.g.,/usr/local/binon Linux/macOS).
If you have Go 1.21+ installed:
go install github.com/kirinyoku/moni@latestNOTE: Make sure
$GOPATH/binis in your system'sPATHto runmonifrom any directory.
git clone https://github.com/kirinyoku/moni.git
cd moni
make build
# Binary created at bin/moni# Rename a single file
moni path/to/image.png
# Rename all regular files in a directory
moni ~/Downloads/
# Rename multiple specific files and folders
moni file1.png folder/ file2.mp4# Only process specific file extensions
moni ~/Downloads/ --include="*.jpg,*.png,*.webp"
# Exclude temporary or unfinished download files
moni ~/Downloads/ --exclude="*.tmp,*.part,*.crdownload"
# Process only the top-level directory (do not enter subfolders)
moni ~/Downloads/ --max-depth=1# Skip interactive prompt and apply renames immediately
moni -y ~/Downloads/
# Quiet mode: suppress all output on success (ideal for cron and CI)
moni -q -y ~/Downloads/
# Undo the most recent rename operation
moni --rollback
# Undo silently
moni --rollback -q -y# Pipe paths from find or other tools (pass -y to apply changes)
find ~/Downloads -type f -name "*.png" | moni -y
# Read null-delimited paths (-0 / --null) to safely handle spaces and special characters
find ~/Downloads -type f -print0 | moni -y -0
# Read paths from standard input explicitly using '-'
git status --porcelain | awk '{print $2}' | moni -y -# Output only renamed paths (pipe into downstream tools like xargs or s3cmd)
moni -y --print ~/Downloads | xargs -I{} aws s3 cp {} s3://my-bucket/
# Output null-separated paths for safe xargs -0 processing
moni -y --print -0 ~/Downloads | xargs -0 -I{} process-file {}
# Output structured JSON mapping of old-to-new paths
moni -y --format=json ~/Downloads | jq '.[] | {from: .old_path, to: .new_path}'
# Output tab-separated mapping (TSV) for processing with awk or while read
moni -y --format=tsv ~/Downloads | while IFS=$'\t' read -r old new; do
ln -s "$new" "$old"
done| Flag | Description | Default |
|---|---|---|
-y |
Skip interactive prompt and apply changes immediately | false |
--print |
Output only resulting renamed paths to stdout (one per line, or \0 with -0) |
false |
--format |
Output structured mapping to stdout ('json' or 'tsv') |
"" |
-q, --quiet |
Suppress diffs, status headers, and completion summaries on success | false |
-0, --null |
Read input paths separated by NUL (\0) characters instead of newlines |
false |
-v |
Enable verbose logging (shows skipped/excluded files on stderr when piping) |
false |
--max-depth |
Maximum directory recursion depth (0 = unlimited) |
0 |
--include |
Comma-separated glob patterns to include (e.g. '*.jpg,*.png') |
"" |
--exclude |
Comma-separated glob patterns to exclude (e.g. '*.tmp,*.part') |
"" |
--rollback |
Restore the latest batch of renamed files | false |
--cache-dir |
Print the rollback journal location and exit | false |
--version |
Print current moni version and exit |
false |
20260127_150405_a1b2c3d4e5f6.jpg
└───┬─────────┘ └────┬─────┘ └─┬┘
│ │ └─── Preserved original extension
│ └───────────── 12-char BLAKE3 content fingerprint
└────────────────────────────── UTC modification timestamp (YYYYMMDD_HHMMSS)
- Small files (≤ 128 KB): The entire file content is hashed to guarantee absolute precision.
- Large files (> 128 KB): Computes a composite hash across the first 4 KB, the last 4 KB, and the 64-bit file size. This prevents heavy I/O spikes and enables instant processing of multi-gigabyte video files or raw images.
- If two files in the same batch share identical content and timestamps (or if a destination name already exists on disk),
moniautomatically resolves the collision by appending sequential counter suffixes:..._1.ext,..._2.ext. - Running
monirepeatedly on an already processed directory is completely idempotent: correctly formatted files are skipped automatically.
Contributions, bug reports, and pull requests are welcome!
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Ensure tests and lint pass (
make test && make lint) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request