@happyvibess/file-organizer
Version:
Simple CLI tool to automatically organize your files by type
128 lines (106 loc) • 3.78 kB
JavaScript
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);