UNPKG

filesops

Version:

Advanced file operations library with search, type detection, size calculation, and permission utilities

301 lines 10.9 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.SizeCalculator = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const util_1 = require("util"); const stat = (0, util_1.promisify)(fs.stat); const readdir = (0, util_1.promisify)(fs.readdir); /** * File and directory size calculation utilities */ class SizeCalculator { /** * Convert bytes to human-readable format */ static formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 B'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const i = Math.floor(Math.log(bytes) / Math.log(k)); const size = parseFloat((bytes / Math.pow(k, i)).toFixed(dm)); return `${size} ${this.UNITS[i]}`; } /** * Get detailed size information for a given byte count */ static getSizeInfo(bytes) { return { bytes, kilobytes: bytes / 1024, megabytes: bytes / (1024 * 1024), gigabytes: bytes / (1024 * 1024 * 1024), terabytes: bytes / (1024 * 1024 * 1024 * 1024), formatted: this.formatBytes(bytes), }; } /** * Get file size */ static async getFileSize(filePath) { try { const stats = await stat(filePath); return this.getSizeInfo(stats.size); } catch (error) { throw new Error(`Unable to get size for file: ${filePath}`); } } /** * Calculate directory size recursively */ static async getDirectorySize(dirPath, includeHidden = false) { const size = await this.calculateDirectorySizeRecursive(dirPath, includeHidden); return this.getSizeInfo(size); } static async calculateDirectorySizeRecursive(dirPath, includeHidden) { let totalSize = 0; try { const items = await readdir(dirPath); for (const item of items) { if (!includeHidden && item.startsWith('.')) { continue; } const itemPath = path.join(dirPath, item); try { const stats = await stat(itemPath); if (stats.isFile()) { totalSize += stats.size; } else if (stats.isDirectory()) { totalSize += await this.calculateDirectorySizeRecursive(itemPath, includeHidden); } } catch (error) { // Skip files/directories that can't be accessed continue; } } } catch (error) { // Skip directories that can't be read } return totalSize; } /** * Get size statistics for a directory (file count, total size, largest files) */ static async getDirectoryStats(dirPath, includeHidden = false) { const stats = await this.gatherDirectoryStats(dirPath, includeHidden); return { totalSize: this.getSizeInfo(stats.totalSize), fileCount: stats.fileCount, directoryCount: stats.directoryCount, largestFiles: stats.largestFiles .sort((a, b) => b.size - a.size) .slice(0, 10) .map(file => ({ path: file.path, size: this.getSizeInfo(file.size), })), averageFileSize: this.getSizeInfo(stats.fileCount > 0 ? stats.totalSize / stats.fileCount : 0), }; } static async gatherDirectoryStats(dirPath, includeHidden, stats = { totalSize: 0, fileCount: 0, directoryCount: 0, largestFiles: [] }) { try { const items = await readdir(dirPath); for (const item of items) { if (!includeHidden && item.startsWith('.')) { continue; } const itemPath = path.join(dirPath, item); try { const itemStats = await stat(itemPath); if (itemStats.isFile()) { stats.totalSize += itemStats.size; stats.fileCount++; stats.largestFiles.push({ path: itemPath, size: itemStats.size }); } else if (itemStats.isDirectory()) { stats.directoryCount++; await this.gatherDirectoryStats(itemPath, includeHidden, stats); } } catch (error) { // Skip files/directories that can't be accessed continue; } } } catch (error) { // Skip directories that can't be read } return stats; } /** * Compare sizes of multiple files or directories */ static async compareItems(paths) { const results = []; for (const itemPath of paths) { try { const stats = await stat(itemPath); let size; if (stats.isFile()) { size = this.getSizeInfo(stats.size); } else if (stats.isDirectory()) { size = await this.getDirectorySize(itemPath); } else { continue; } results.push({ path: itemPath, size, isDirectory: stats.isDirectory(), }); } catch (error) { // Skip items that can't be accessed continue; } } return results.sort((a, b) => b.size.bytes - a.size.bytes); } /** * Find the largest files in a directory */ static async findLargestFiles(dirPath, limit = 10, includeHidden = false) { const files = []; await this.collectFiles(dirPath, files, includeHidden); return files .sort((a, b) => b.size - a.size) .slice(0, limit) .map(file => ({ path: file.path, size: this.getSizeInfo(file.size), })); } static async collectFiles(dirPath, files, includeHidden) { try { const items = await readdir(dirPath); for (const item of items) { if (!includeHidden && item.startsWith('.')) { continue; } const itemPath = path.join(dirPath, item); try { const stats = await stat(itemPath); if (stats.isFile()) { files.push({ path: itemPath, size: stats.size }); } else if (stats.isDirectory()) { await this.collectFiles(itemPath, files, includeHidden); } } catch (error) { // Skip files/directories that can't be accessed continue; } } } catch (error) { // Skip directories that can't be read } } /** * Calculate size of files matching a pattern */ static async getSizeByPattern(dirPath, pattern, includeHidden = false) { let totalSize = 0; await this.collectSizeByPattern(dirPath, pattern, includeHidden, (size) => { totalSize += size; }); return this.getSizeInfo(totalSize); } static async collectSizeByPattern(dirPath, pattern, includeHidden, callback) { try { const items = await readdir(dirPath); for (const item of items) { if (!includeHidden && item.startsWith('.')) { continue; } const itemPath = path.join(dirPath, item); try { const stats = await stat(itemPath); if (stats.isFile() && pattern.test(item)) { callback(stats.size); } else if (stats.isDirectory()) { await this.collectSizeByPattern(itemPath, pattern, includeHidden, callback); } } catch (error) { // Skip files/directories that can't be accessed continue; } } } catch (error) { // Skip directories that can't be read } } /** * Parse human-readable size string to bytes */ static parseSize(sizeString) { const match = sizeString.match(/^(\d+(?:\.\d+)?)\s*([KMGTPE]?B?)$/i); if (!match) { throw new Error(`Invalid size format: ${sizeString}`); } const value = parseFloat(match[1]); const unit = (match[2] || 'B').toUpperCase(); const multipliers = { 'B': 1, 'KB': 1024, 'MB': 1024 * 1024, 'GB': 1024 * 1024 * 1024, 'TB': 1024 * 1024 * 1024 * 1024, 'PB': 1024 * 1024 * 1024 * 1024 * 1024, }; return Math.round(value * (multipliers[unit] || 1)); } } exports.SizeCalculator = SizeCalculator; SizeCalculator.UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; //# sourceMappingURL=size.js.map