MCPcopy
hub / github.com/modelcontextprotocol/servers / tailFile

Function tailFile

src/filesystem/lib.ts:285–334  ·  view source on GitHub ↗
(filePath: string, numLines: number)

Source from the content-addressed store, hash-verified

283
284// Memory-efficient implementation to get the last N lines of a file
285export async function tailFile(filePath: string, numLines: number): Promise<string> {
286 const CHUNK_SIZE = 1024; // Read 1KB at a time
287 const stats = await fs.stat(filePath);
288 const fileSize = stats.size;
289
290 if (fileSize === 0) return '';
291
292 // Open file for reading
293 const fileHandle = await fs.open(filePath, 'r');
294 try {
295 const lines: string[] = [];
296 let position = fileSize;
297 let chunk = Buffer.alloc(CHUNK_SIZE);
298 let linesFound = 0;
299 let remainingText = '';
300
301 // Read chunks from the end of the file until we have enough lines
302 while (position > 0 && linesFound < numLines) {
303 const size = Math.min(CHUNK_SIZE, position);
304 position -= size;
305
306 const { bytesRead } = await fileHandle.read(chunk, 0, size, position);
307 if (!bytesRead) break;
308
309 // Get the chunk as a string and prepend any remaining text from previous iteration
310 const readData = chunk.slice(0, bytesRead).toString('utf-8');
311 const chunkText = readData + remainingText;
312
313 // Split by newlines and count
314 const chunkLines = normalizeLineEndings(chunkText).split('\n');
315
316 // If this isn't the end of the file, the first line is likely incomplete
317 // Save it to prepend to the next chunk
318 if (position > 0) {
319 remainingText = chunkLines[0];
320 chunkLines.shift(); // Remove the first (incomplete) line
321 }
322
323 // Add lines to our result (up to the number we need)
324 for (let i = chunkLines.length - 1; i >= 0 && linesFound < numLines; i--) {
325 lines.unshift(chunkLines[i]);
326 linesFound++;
327 }
328 }
329
330 return lines.join('\n');
331 } finally {
332 await fileHandle.close();
333 }
334}
335
336// New function to get the first N lines of a file
337export async function headFile(filePath: string, numLines: number): Promise<string> {

Callers 2

readTextFileHandlerFunction · 0.85
lib.test.tsFile · 0.85

Calls 1

normalizeLineEndingsFunction · 0.85

Tested by

no test coverage detected