UNPKG

dir-analysis-tool

Version:

A comprehensive cross-platform CLI tool for advanced directory analysis with file classification, duplicate detection, large file identification, interactive mode, HTML reports, and multiple export formats. Perfect for disk cleanup, storage audits, and pr

185 lines 6.81 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.FileFilter = exports.EmptyFileDetector = exports.LargeFileDetector = exports.DuplicateDetector = void 0; const crypto = __importStar(require("crypto")); const fs_1 = require("fs"); const utils_1 = require("./utils"); class DuplicateDetector { fileHashes = new Map(); processedFiles = 0; totalFiles = 0; async detectDuplicates(filePaths, progressCallback) { this.fileHashes.clear(); this.processedFiles = 0; this.totalFiles = filePaths.length; if (progressCallback) { progressCallback(0, this.totalFiles, 'Starting duplicate detection...'); } const batchSize = 50; for (let i = 0; i < filePaths.length; i += batchSize) { const batch = filePaths.slice(i, i + batchSize); await Promise.all(batch.map(filePath => this.processFile(filePath, progressCallback))); } return this.generateDuplicateGroups(); } async processFile(filePath, progressCallback) { try { const hash = await this.calculateFileHash(filePath); if (!this.fileHashes.has(hash)) { this.fileHashes.set(hash, []); } this.fileHashes.get(hash).push(filePath); this.processedFiles++; if (progressCallback) { progressCallback(this.processedFiles, this.totalFiles, filePath); } } catch (error) { this.processedFiles++; if (progressCallback) { progressCallback(this.processedFiles, this.totalFiles); } } } async calculateFileHash(filePath) { const hash = crypto.createHash('md5'); const stream = await fs_1.promises.readFile(filePath); hash.update(stream); return hash.digest('hex'); } async generateDuplicateGroups() { const groups = []; for (const [hash, files] of this.fileHashes) { if (files.length > 1) { try { const stats = await fs_1.promises.stat(files[0]); const size = stats.size; const totalWastedSpace = size * (files.length - 1); groups.push({ hash, size, sizeFormatted: (0, utils_1.formatSize)(size), files: [...files], totalWastedSpace, totalWastedSpaceFormatted: (0, utils_1.formatSize)(totalWastedSpace) }); } catch (error) { // Skip if we can't get file stats } } } return groups.sort((a, b) => b.totalWastedSpace - a.totalWastedSpace); } } exports.DuplicateDetector = DuplicateDetector; class LargeFileDetector { static detectLargeFiles(files, threshold) { return files .filter(file => file.size >= threshold) .sort((a, b) => b.size - a.size) .map(file => ({ path: file.path, size: file.size, sizeFormatted: (0, utils_1.formatSize)(file.size) })); } static getTopLargestFiles(files, count) { return files .sort((a, b) => b.size - a.size) .slice(0, count) .map(file => ({ path: file.path, size: file.size, sizeFormatted: (0, utils_1.formatSize)(file.size) })); } } exports.LargeFileDetector = LargeFileDetector; class EmptyFileDetector { static async detectEmptyFiles(files) { const emptyFiles = []; for (const file of files) { if (file.size === 0) { try { const stats = await fs_1.promises.stat(file.path); emptyFiles.push({ path: file.path, modifiedDate: stats.mtime }); } catch (error) { // Skip files that can't be accessed } } } return emptyFiles.sort((a, b) => b.modifiedDate.getTime() - a.modifiedDate.getTime()); } } exports.EmptyFileDetector = EmptyFileDetector; class FileFilter { static filterBySize(files, minSize, maxSize) { return files.filter(file => { if (minSize !== undefined && file.size < minSize) return false; if (maxSize !== undefined && file.size > maxSize) return false; return true; }); } static async filterByDate(files, dateFrom, dateTo) { if (!dateFrom && !dateTo) return files; const filteredFiles = []; for (const file of files) { try { const stats = await fs_1.promises.stat(file.path); const modifiedDate = stats.mtime; if (dateFrom && modifiedDate < dateFrom) continue; if (dateTo && modifiedDate > dateTo) continue; filteredFiles.push(file); } catch (error) { // Skip files that can't be accessed } } return filteredFiles; } } exports.FileFilter = FileFilter; //# sourceMappingURL=advanced-analysis.js.map