Skip to content

Instantly share code, notes, and snippets.

@isurfer21
Created June 6, 2026 11:13
Show Gist options
  • Select an option

  • Save isurfer21/dd95c1cbfec43c9c38cb6f0b56a8e251 to your computer and use it in GitHub Desktop.

Select an option

Save isurfer21/dd95c1cbfec43c9c38cb6f0b56a8e251 to your computer and use it in GitHub Desktop.
Bun based system utility to handle pattern matching, sorting, and renaming files flawlessly in batch.
import { readdirSync } from "node:fs";
import { rename } from "node:fs/promises";
import { join } from "node:path";
const [searchPattern, replacePattern] = Bun.argv.slice(2);
if (!searchPattern || !replacePattern) {
console.log("Usage:\n bun rename-files.ts '<search_pattern>' '<replace_pattern>'");
console.log("Example:\n bun rename-files.ts 'Screenshot *.png' 'pic-*.png'");
process.exit(1);
}
const currentDir = process.cwd();
// Fix: Split the pattern by '*' to get literal prefix and suffix strings
// e.g., "Screenshot *.png" -> prefix: "Screenshot ", suffix: ".png"
const parts = searchPattern.split("*");
const prefix = parts[0] || "";
const suffix = parts[1] || "";
console.log(`Working Directory: ${currentDir}`);
console.log(`Matching files starting with "${prefix}" and ending with "${suffix}"`);
console.log("--------------------------------------------");
const allFiles = readdirSync(currentDir, { withFileTypes: true });
// Filter files safely using pure string matching (case-insensitive)
const matchedFiles = allFiles
.filter(entry => {
if (!entry.isFile()) return false;
const name = entry.name.toLowerCase();
return name.startsWith(prefix.toLowerCase()) && name.endsWith(suffix.toLowerCase());
})
.map(entry => entry.name);
// Sort them in ascending sequence before numbering them
matchedFiles.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));
if (matchedFiles.length === 0) {
console.log("No files matched the pattern in this directory.");
process.exit(0);
}
let count = 0;
for (let i = 0; i < matchedFiles.length; i++) {
const file = matchedFiles[i];
// Use the loop index + 1 as the counter string
const counterStr = (i + 1).toString();
const newFileName = replacePattern.replace("*", counterStr);
console.log(`Renaming: ${file} -> ${newFileName}`);
await rename(join(currentDir, file), join(currentDir, newFileName));
count++;
}
console.log("--------------------------------------------");
console.log(`Successfully renamed ${count} file(s) in ascending order.`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment