filesops
Version:
Advanced file operations library with search, type detection, size calculation, and permission utilities
203 lines • 7.66 kB
JavaScript
;
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.FileSearch = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const util_1 = require("util");
const readdir = (0, util_1.promisify)(fs.readdir);
const stat = (0, util_1.promisify)(fs.stat);
const access = (0, util_1.promisify)(fs.access);
/**
* Advanced file search with multiple filtering options
*/
class FileSearch {
static async getFileInfo(filePath) {
const stats = await stat(filePath);
const parsedPath = path.parse(filePath);
return {
path: filePath,
name: parsedPath.base,
extension: parsedPath.ext,
size: stats.size,
isDirectory: stats.isDirectory(),
isFile: stats.isFile(),
createdAt: stats.birthtime,
modifiedAt: stats.mtime,
accessedAt: stats.atime,
};
}
static matchesPattern(filename, pattern, caseSensitive) {
if (pattern instanceof RegExp) {
return pattern.test(filename);
}
const targetName = caseSensitive ? filename : filename.toLowerCase();
const targetPattern = caseSensitive ? pattern : pattern.toLowerCase();
// Support glob-like patterns
const regexPattern = targetPattern
.replace(/\./g, '\\.')
.replace(/\*/g, '.*')
.replace(/\?/g, '.');
return new RegExp(`^${regexPattern}$`).test(targetName);
}
static matchesOptions(fileInfo, options) {
// Extension filter
if (options.extensions && options.extensions.length > 0) {
const ext = fileInfo.extension.toLowerCase();
const extensions = options.extensions.map(e => e.toLowerCase().startsWith('.') ? e : `.${e}`);
if (!extensions.includes(ext)) {
return false;
}
}
// Size filters
if (options.maxSize && fileInfo.size > options.maxSize) {
return false;
}
if (options.minSize && fileInfo.size < options.minSize) {
return false;
}
// Date filters
if (options.modifiedSince && fileInfo.modifiedAt < options.modifiedSince) {
return false;
}
if (options.modifiedBefore && fileInfo.modifiedAt > options.modifiedBefore) {
return false;
}
return true;
}
/**
* Search for files in a directory with advanced filtering options
*/
static async search(searchPath, options = {}) {
const files = [];
const directories = [];
await this.searchRecursive(searchPath, options, files, directories, 0);
const totalSize = files.reduce((sum, file) => sum + file.size, 0);
return {
files,
directories,
totalFiles: files.length,
totalDirectories: directories.length,
totalSize,
};
}
static async searchRecursive(currentPath, options, files, directories, currentDepth) {
// Check depth limit
if (options.maxDepth !== undefined && currentDepth > options.maxDepth) {
return;
}
try {
const items = await readdir(currentPath);
for (const item of items) {
// Skip hidden files if not included
if (!options.includeHidden && item.startsWith('.')) {
continue;
}
const itemPath = path.join(currentPath, item);
try {
const fileInfo = await this.getFileInfo(itemPath);
// Handle symlinks
if (!options.followSymlinks && (await stat(itemPath)).isSymbolicLink()) {
continue;
}
if (fileInfo.isDirectory) {
if (this.matchesPattern(fileInfo.name, options.pattern || '*', options.caseSensitive || false)) {
directories.push(fileInfo);
}
// Recursively search subdirectories
await this.searchRecursive(itemPath, options, files, directories, currentDepth + 1);
}
else if (fileInfo.isFile) {
// Check if file matches all criteria
if (this.matchesPattern(fileInfo.name, options.pattern || '*', options.caseSensitive || false) &&
this.matchesOptions(fileInfo, options)) {
files.push(fileInfo);
}
}
}
catch (error) {
// Skip files that can't be accessed
continue;
}
}
}
catch (error) {
// Skip directories that can't be read
return;
}
}
/**
* Find files by name pattern
*/
static async findByName(searchPath, pattern, caseSensitive = false) {
const result = await this.search(searchPath, { pattern, caseSensitive });
return result.files;
}
/**
* Find files by extension
*/
static async findByExtension(searchPath, extensions) {
const result = await this.search(searchPath, { extensions });
return result.files;
}
/**
* Find files larger than specified size
*/
static async findLargeFiles(searchPath, minSize) {
const result = await this.search(searchPath, { minSize });
return result.files.sort((a, b) => b.size - a.size);
}
/**
* Find recently modified files
*/
static async findRecentFiles(searchPath, since) {
const result = await this.search(searchPath, { modifiedSince: since });
return result.files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
}
/**
* Check if a file or directory exists and is accessible
*/
static async exists(filePath) {
try {
await access(filePath, fs.constants.F_OK);
return true;
}
catch {
return false;
}
}
}
exports.FileSearch = FileSearch;
//# sourceMappingURL=search.js.map