Scripts

folder-sizes

Calcula e ordena tamanhos de pastas no diretório atual.

Como usar (TypeScript)

  1. 1.Instale o Bun: https://bun.sh
  2. 2.Baixe o script para a pasta do seu projeto (mesmo diretório do package.json)
  3. 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