diff --git a/index.js b/index.js index 0437574..7d2928c 100644 --- a/index.js +++ b/index.js @@ -1,130 +1,203 @@ -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'); - -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() { - const config = await getConfig(); - umbenennenSync(config.folderPath, config.suffix); - console.log('Fertig!'); -} - -main(); +/* +* 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();