Scripts
folder-sizes
Calcula e ordena tamanhos de pastas no diretório atual.
Como usar (TypeScript)
- 1.Instale o Bun: https://bun.sh
- 2.Baixe o script para a pasta do seu projeto (mesmo diretório do package.json)
- 3.Execute: bun {scriptPath}
1#!/usr/bin/env bun
2
3import { readdirSync, statSync } from "fs";
4import { join } from "path";
5import { cpus } from "os";
6import { $ } from "bun";
7
8interface FolderSize {
9 name: string;
10 size: number;
11}
12
13const SIZE_UNITS = ["B", "KB", "MB", "GB", "TB"] as const;
14const BYTES_PER_UNIT = 1024;
15const BYTES_PER_KB = 1024;
16const SHUTDOWN_TIMEOUT_MS = 1000;
17
18let isShuttingDown = false;
19const activeProcesses = new Set<Promise<FolderSize>>();
20
21function formatSize(bytes: number): string {
22 let size = bytes;
23 let unitIndex = 0;
24
25 while (size >= BYTES_PER_UNIT && unitIndex < SIZE_UNITS.length - 1) {
26 size /= BYTES_PER_UNIT;
27 unitIndex++;
28 }
29
30 return `${size.toFixed(2)} ${SIZE_UNITS[unitIndex]}`;
31}
32
33async function processBatch<T, R>(
34 items: T[],
35 processor: (item: T) => Promise<R>,
36 concurrency: number
37): Promise<R[]> {
38 const results: R[] = [];
39
40 for (let i = 0; i < items.length; i += concurrency) {
41 if (isShuttingDown) {
42 throw new Error("Process interrupted by user");
43 }
44
45 const batch = items.slice(i, i + concurrency);
46 const batchPromises = batch.map(processor);
47 batchPromises.forEach((p) => activeProcesses.add(p));
48
49 try {
50 const batchResults = await Promise.all(batchPromises);
51 results.push(...batchResults);
52 } finally {
53 batchPromises.forEach((p) => activeProcesses.delete(p));
54 }
55 }
56
57 return results;
58}
59
60// Handle CTRL+C gracefully
61process.on("SIGINT", async () => {
62 if (isShuttingDown) {
63 return;
64 }
65
66 isShuttingDown = true;
67 console.log("\n\nReceived SIGINT (CTRL+C). Shutting down gracefully...");
68 console.log("Killing all running processes...");
69
70 // Wait a bit for active processes to finish or timeout
71 await Promise.race([
72 Promise.allSettled(Array.from(activeProcesses)),
73 new Promise((resolve) => setTimeout(resolve, SHUTDOWN_TIMEOUT_MS)),
74 ]);
75
76 console.log("Cleanup complete. Exiting.");
77 process.exit(0);
78});
79
80async function main(): Promise<void> {
81 const targetDir = process.cwd();
82 const cpuCount = cpus().length;
83
84 console.log(`Analyzing folders in: ${targetDir}`);
85 console.log(`Using ${cpuCount} CPU cores for parallel processing\n`);
86
87 const items = readdirSync(targetDir);
88
89 const directories = items.filter((item) => {
90 try {
91 const itemPath = join(targetDir, item);
92 const stats = statSync(itemPath);
93 return stats.isDirectory();
94 } catch {
95 return false;
96 }
97 });
98
99 console.log(`Found ${directories.length} folders to analyze\n`);
100
101 const folders = await processBatch(
102 directories,
103 async (item) => {
104 console.log(`Calculating size of: ${item}...`);
105 const itemPath = join(targetDir, item);
106
107 try {
108 // Use du command via Bun's $ API for actual OS-level parallel processing
109 const result = await $`du -sk ${itemPath}`.quiet();
110 const output = result.text().trim();
111 const sizeInKB = parseInt(output.split("\t")[0], 10);
112 const sizeInBytes = sizeInKB * BYTES_PER_KB;
113
114 return { name: item, size: sizeInBytes };
115 } catch (error) {
116 console.error(`Error calculating size for ${item}:`, error);
117 return { name: item, size: 0 };
118 }
119 },
120 cpuCount
121 );
122
123 // Sort by size (largest first)
124 folders.sort((a, b) => b.size - a.size);
125
126 console.log(`\n--- Folder Sizes (Largest to Smallest) ---`);
127 console.log(`Path: ${targetDir}\n`);
128
129 for (const folder of folders) {
130 console.log(`${formatSize(folder.size).padStart(12)} - ${folder.name}`);
131 }
132
133 console.log(`\nTotal folders analyzed: ${folders.length}`);
134}
135
136main().catch((error) => {
137 console.error("Error:", error);
138 process.exit(1);
139});
140