UNPKG

@happyvibess/file-organizer

Version:

Simple CLI tool to automatically organize your files by type

128 lines (106 loc) 3.78 kB
#!/usr/bin/env node const fs = require('fs-extra'); const path = require('path'); const chalk = require('chalk'); const { program } = require('commander'); const ora = require('ora'); const { version } = require('../package.json'); // File type mappings const fileTypes = { images: ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp'], documents: ['.pdf', '.doc', '.docx', '.txt', '.md', '.rtf', '.odt'], audio: ['.mp3', '.wav', '.flac', '.m4a', '.aac'], video: ['.mp4', '.avi', '.mkv', '.mov', '.wmv'], archives: ['.zip', '.rar', '.7z', '.tar', '.gz'], code: ['.js', '.py', '.java', '.cpp', '.html', '.css', '.php', '.rb'] }; async function organizeFiles(directory, options) { const spinner = ora('Analyzing directory...').start(); try { // Ensure directory exists if (!fs.existsSync(directory)) { throw new Error(`Directory "${directory}" does not exist`); } // Get all files in directory const files = await fs.readdir(directory); const stats = { processed: 0, skipped: 0, errors: [] }; // Create category directories if they don't exist if (!options.dryRun) { for (const category of Object.keys(fileTypes)) { const categoryPath = path.join(directory, category); if (!fs.existsSync(categoryPath)) { await fs.mkdir(categoryPath); } } } spinner.text = 'Organizing files...'; // Process each file for (const file of files) { const filePath = path.join(directory, file); const stat = await fs.stat(filePath); // Skip if it's a directory if (stat.isDirectory()) continue; const ext = path.extname(file).toLowerCase(); let category = 'misc'; // Determine file category for (const [type, extensions] of Object.entries(fileTypes)) { if (extensions.includes(ext)) { category = type; break; } } const targetDir = path.join(directory, category); const targetPath = path.join(targetDir, file); if (options.dryRun) { console.log(chalk.blue(`Would move ${file} to ${category}/`)); stats.processed++; continue; } try { if (!fs.existsSync(targetDir)) { await fs.mkdir(targetDir); } await fs.move(filePath, targetPath, { overwrite: false }); if (options.verbose) { console.log(chalk.green(`✓ Moved ${file} to ${category}/`)); } stats.processed++; } catch (error) { stats.errors.push({ file, error: error.message }); stats.skipped++; if (options.verbose) { console.log(chalk.red(`✗ Failed to move ${file}: ${error.message}`)); } } } // Display results spinner.succeed(chalk.green(`Organization complete!`)); console.log(chalk.cyan(`\nResults:`)); console.log(`Files processed: ${stats.processed}`); console.log(`Files skipped: ${stats.skipped}`); if (stats.errors.length > 0 && options.verbose) { console.log(chalk.yellow('\nErrors encountered:')); stats.errors.forEach(({ file, error }) => { console.log(chalk.red(` ${file}: ${error}`)); }); } } catch (error) { spinner.fail(chalk.red(`Error: ${error.message}`)); process.exit(1); } } // Set up CLI program .version(version) .description('Organize files in a directory by type') .argument('[directory]', 'Target directory (defaults to current directory)') .option('-d, --dry-run', 'Show what would be done without making changes') .option('-v, --verbose', 'Show detailed output') .action(async (directory = process.cwd(), options) => { await organizeFiles(directory, options); }); program.parse(process.argv);