file-renamer-cli/index.js
2025-05-17 08:58:26 +00:00

204 lines
6.7 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Projekt: File Renamer CLI
* Beschreibung: Ein rekursives CLI-Tool zum Umbenennen von Dateien mit Suffix.
* Autor: M_Viper
* Lizenz: MIT
* GitHub: https://git.viper.ipv64.net/M_Viper/file-renamer-cli
* Webseite: https://m-viper.de
*/
const fs = require('fs');
const path = require('path');
const os = require('os');
const readline = require('readline');
const configPath = path.join(os.homedir(), 'Documents', 'config.json');
// ================== Banner ==================
function greenMessage(text) {
console.log('\x1b[32m%s\x1b[0m', text);
}
function centerText(text, width) {
const len = text.length;
if (len >= width) return text;
const leftPadding = Math.floor((width - len) / 2);
return ' '.repeat(leftPadding) + text;
}
function showAsciiLogo() {
const width = process.stdout.columns || 80; // Terminalbreite, fallback 80
const logoLines = [
'███████╗██╗██╗ ███████╗███╗ ██╗ █████╗ ███╗ ███╗███████╗ ██████╗██╗ ██╗',
'██╔════╝██║██║ ██╔════╝████╗ ██║██╔══██╗████╗ ████║██╔════╝ ██╔════╝██║ ██║',
'█████╗ ██║██║ █████╗ ██╔██╗ ██║███████║██╔████╔██║█████╗ ██║ ██║ ██║',
'██╔══╝ ██║██║ ██╔══╝ ██║╚██╗██║██╔══██║██║╚██╔╝██║██╔══╝ ██║ ██║ ██║',
'██║ ██║███████╗███████╗██║ ╚████║██║ ██║██║ ╚═╝ ██║███████╗ ╚██████╗███████╗██║',
'╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚══════╝╚═╝',
];
console.log('\x1b[32m'); // grün starten
for (const line of logoLines) {
console.log(centerText(line, width));
}
console.log('\x1b[0m'); // Farbe zurücksetzen
console.log('');
}
function showBanner() {
console.clear();
showAsciiLogo();
const width = process.stdout.columns || 60; // Breite des Terminals, fallback 60
const bannerLines = [
'Version 1.0',
'Script by',
'@M_Viper',
'__________________________',
'',
'Git: https://git.viper.ipv64.net/M_Viper/file-renamer-cli',
];
// Obere Rahmenlinie
greenMessage('╔' + '═'.repeat(width - 2) + '╗');
// Bannerzeilen mit Rahmen und Zentrierung
for (const line of bannerLines) {
const centered = centerText(line, width - 4); // 4 wegen Rahmen links und rechts + Leerzeichen
greenMessage('║ ' + centered + ' ║');
}
// Untere Rahmenlinie
greenMessage('╚' + '═'.repeat(width - 2) + '╝');
greenMessage('');
}
// ============================================
function saveConfig(config) {
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
}
function loadConfig() {
if (fs.existsSync(configPath)) {
try {
return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
} catch {
return null;
}
}
return null;
}
function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise(resolve => rl.question(query, ans => {
rl.close();
resolve(ans.trim());
}));
}
async function getConfig() {
const existingConfig = loadConfig();
if (existingConfig?.folderPath && existingConfig?.suffix) {
console.log(`Verwende gespeicherte Konfiguration:`);
console.log(`Ordner: ${existingConfig.folderPath}`);
console.log(`Suffix: ${existingConfig.suffix}`);
return existingConfig;
}
console.log('Möchtest du den automatischen Ordner nutzen?');
console.log('1 = Ja (Desktop\\Filme)');
console.log('2 = Benutzerdefinierter Ordner');
const antwort = await askQuestion('Deine Wahl (1 oder 2): ');
let folderPath;
if (antwort === '1') {
folderPath = path.join(os.homedir(), 'Desktop', 'Filme');
console.log(`Automatischer Ordner gewählt: ${folderPath}`);
} else if (antwort === '2') {
folderPath = await askQuestion('Bitte gib den vollständigen Pfad zum Ordner ein:\n');
} else {
console.log('Ungültige Eingabe, bitte versuche es nochmal.');
return getConfig();
}
const suffix = await askQuestion('Welcher Text soll am Ende der Dateinamen hinzugefügt werden? (z.B. @Name)\n');
const config = { folderPath, suffix };
saveConfig(config);
return config;
}
function umbenennenSync(pfad, suffix) {
console.log('Prüfe Ordner:', pfad);
if (!fs.existsSync(pfad)) {
console.log('Ordner existiert nicht, erstelle:', pfad);
fs.mkdirSync(pfad, { recursive: true });
return;
}
const eintraege = fs.readdirSync(pfad, { withFileTypes: true });
if (eintraege.length === 0) {
console.log('Ordner ist leer:', pfad);
}
for (const eintrag of eintraege) {
const vollerPfad = path.join(pfad, eintrag.name);
if (eintrag.isDirectory()) {
if (
eintrag.name === 'System Volume Information' ||
eintrag.name.startsWith('$') ||
eintrag.name.startsWith('.')
) {
console.log('Überspringe geschützten/verborgenen Ordner:', vollerPfad);
continue;
}
console.log('Betrete Unterordner:', vollerPfad);
umbenennenSync(vollerPfad, suffix);
} else if (eintrag.isFile()) {
const ext = path.extname(eintrag.name);
const name = path.basename(eintrag.name, ext);
if (name.endsWith(` ${suffix}`)) {
console.log('Datei schon umbenannt, überspringe:', eintrag.name);
continue;
}
const neuerName = `${name} ${suffix}${ext}`;
const neuerPfad = path.join(pfad, neuerName);
try {
fs.renameSync(vollerPfad, neuerPfad);
console.log(`Umbenannt: ${eintrag.name}${neuerName}`);
} catch (e) {
console.error(`Fehler bei ${eintrag.name}:`, e.message);
if (e.code === 'EPERM' || e.code === 'EACCES') {
console.error('Keine Zugriffsrechte oder Datei geschützt. Übersprungen.');
}
}
} else {
console.log('Kein Datei- oder Ordner-Eintrag, überspringe:', eintrag.name);
}
}
}
async function main() {
showBanner(); // Banner anzeigen
const config = await getConfig();
umbenennenSync(config.folderPath, config.suffix);
console.log('Fertig!');
}
main();