mirror of
https://github.com/spacebarchat/server.git
synced 2026-10-23 13:03:08 +00:00
Quick and dirty util scripts, trim node modules
This commit is contained in:
1 parent
7b48c2bdd1
commit
00b2a18cdb
4 files changed
+362
-106
No files matched your search
+2
-1
@@ -63,7 +63,8 @@ pkgs.buildNpmPackage {
|
||||
|
||||
# remove packages not needed for production, or at least try to...
|
||||
npm prune --omit dev --no-save $npmInstallFlags "''${npmInstallFlagsArray[@]}" $npmFlags "''${npmFlagsArray[@]}"
|
||||
${./nix/trimNodeModules.sh}
|
||||
rm -v dist/src.tsbuildinfo
|
||||
time ${./nix/trimNodeModules.sh}
|
||||
|
||||
# Copy outputs
|
||||
echo "Installing package into $out"
|
||||
|
||||
+146
-105
@@ -1,123 +1,164 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
# We don't care about CLI scripts:
|
||||
echo "Removing CLI scripts..."
|
||||
for f in ./node_modules/.bin/*; do
|
||||
rm -f "$(realpath $f)" $f
|
||||
done
|
||||
find ./node_modules -type d -name '.bin' | while read -r dir; do
|
||||
echo "Removing CLI scripts from $dir..."
|
||||
for f in "$dir"/*; do
|
||||
rm -f "$(realpath $f)" $f
|
||||
done
|
||||
done
|
||||
|
||||
# Unused stuff in specific packages
|
||||
time (
|
||||
echo -n "Removing unused module features: "
|
||||
rm -rf ./node_modules/typeorm/browser && echo -n .
|
||||
rm -rf ./node_modules/typeorm/cli && echo -n .
|
||||
rm -rf ./node_modules/typeorm/driver/**/*.map && echo -n .
|
||||
rm -rf ./node_modules/ajv/lib && echo -n .
|
||||
# rm -rf ./node_modules/ajv/dist/refs && echo -n .
|
||||
)
|
||||
|
||||
time (
|
||||
echo -en "\nRemoving specific known large unneeded packages: "
|
||||
rm -rf ./node_modules/typescript && echo -n .
|
||||
rm -rf ./node_modules/@typescript/native-preview && echo -n .
|
||||
rm -rf ./node_modules/ts-node && echo -n .
|
||||
rm -rf ./node_modules/node-gyp && echo -n .
|
||||
rm -rf ./node_modules/node-gyp-build-optional-packages && echo -n .
|
||||
rm -rf ./node_modules/discord-protos/{discord_protos,scripts} && echo -n .
|
||||
rm -f ./node_modules/.package-lock.json && echo -n .
|
||||
rm -rf ./node_modules/@jimp/plugin-print/fonts && echo -n . # duplicated in dist/fonts
|
||||
for i in ./node_modules/@jimp/*; do
|
||||
if [ -d "$i/dist/commonjs" ]; then
|
||||
rm -rf "$i/dist/commonjs" && echo -n .
|
||||
fi
|
||||
if [ -d "$i/dist/browser" ]; then
|
||||
rm -rf "$i/dist/browser" && echo -n .
|
||||
fi
|
||||
done
|
||||
|
||||
find ./node_modules -name '*.map' -type f -delete -printf .
|
||||
)
|
||||
|
||||
# sources
|
||||
echo "Removing source files..."
|
||||
find ./node_modules -name '*.ts' -type f -delete
|
||||
find ./node_modules -name '*.mts' -type f -delete
|
||||
find ./node_modules -name '*.cts' -type f -delete
|
||||
find ./node_modules -name '*.coffee' -type f -delete
|
||||
find ./node_modules -name '*.rs' -type f -delete
|
||||
find ./node_modules -name '*.c' -type f -delete
|
||||
find ./node_modules -name '*.cc' -type f -delete
|
||||
find ./node_modules -name '*.cpp' -type f -delete
|
||||
find ./node_modules -name '*.h' -type f -delete
|
||||
find ./node_modules -name '*.hh' -type f -delete
|
||||
find ./node_modules -name '*.hpp' -type f -delete
|
||||
time (
|
||||
echo -en "\nRemoving source files: "
|
||||
# typescript
|
||||
echo -en "\n - Typescript: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(ts|mts|cts|d\.ts)$' -type f -delete -printf .
|
||||
# C/C++
|
||||
echo -en "\n - C/C++: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(c|cc|cpp|h|hh|hpp)$' -type f -delete -printf .
|
||||
# rust
|
||||
echo -en "\n - Rust: "
|
||||
find ./node_modules -name '*.rs' -type f -delete -printf .
|
||||
# coffeescript
|
||||
echo -en "\n - Coffeescript: "
|
||||
find ./node_modules -name '*.coffee' -type f -delete -printf .
|
||||
)
|
||||
|
||||
# standard C/C++ build artifacts
|
||||
echo "Removing build artifacts..."
|
||||
find ./node_modules -name '*.o' -type f -delete
|
||||
find ./node_modules -name '*.a' -type f -delete
|
||||
find ./node_modules -name '*.d' -type f -delete
|
||||
time (
|
||||
echo -en "\nRemoving build artifacts: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(o|a|d|obj)$' -type f -delete -printf .
|
||||
)
|
||||
|
||||
# ???
|
||||
echo "Removing other random build artifacts..."
|
||||
# find ./node_modules -wholename '*build/Release/obj' -type d -exec rm -rfv {} +
|
||||
# find ./node_modules -wholename '*build/Release/obj.target' -type d -exec rm -rfv {} +
|
||||
find ./node_modules -name 'obj' -type f -delete
|
||||
find ./node_modules -name 'obj.target' -type f -delete
|
||||
find ./node_modules -name '*.ar-file-list' -type f -delete
|
||||
find ./node_modules -name '*.stamp' -type f -delete
|
||||
find ./node_modules -name '*musl.node' -type f -delete
|
||||
rm -rf ./node_modules/typescript
|
||||
rm -rf ./node_modules/@typescript/native-preview
|
||||
rm -rf ./node_modules/ts-node
|
||||
rm -rf ./node_modules/node-gyp
|
||||
rm -rf ./node_modules/node-gyp-build-optional-packages
|
||||
rm -rf ./node_modules/discord-protos/{discord_protos,scripts}
|
||||
time (
|
||||
echo -en "\nRemoving other random build artifacts: "
|
||||
# find ./node_modules -wholename '*build/Release/obj' -type d -exec rm -rfv {} +
|
||||
# find ./node_modules -wholename '*build/Release/obj.target' -type d -exec rm -rfv {} +
|
||||
find ./node_modules -iname 'obj' -type f -delete -printf .
|
||||
find ./node_modules -iname 'obj.target' -type f -delete -printf .
|
||||
find ./node_modules -iname '*.ar-file-list' -type f -delete -printf .
|
||||
find ./node_modules -iname '*.stamp' -type f -delete -printf .
|
||||
find ./node_modules -iname '*musl.node' -type f -delete -printf .
|
||||
|
||||
# rm -rf ./node_modules/typescript-json-schema
|
||||
rm -rf ./node_modules/node-gyp
|
||||
find ./node_modules -name '@types' -type d -exec rm -rf {} +
|
||||
# rm -rf ./node_modules/typescript-json-schema
|
||||
rm -rf ./node_modules/node-gyp && echo -n .
|
||||
find ./node_modules -iname '@types' -type d -exec rm -rf {} + -printf .
|
||||
)
|
||||
|
||||
echo "Removing random common files..."
|
||||
find ./node_modules -name 'test' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name 'tests' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name 'examples' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name 'coverage' -type d -exec rm -rf {} + # Why would you ship coverage reports in artifacts??
|
||||
find ./node_modules -name '.nyc_output' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name 'doc' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name 'docs' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '.idea' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '.github' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '__snapshots__' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '.turbo' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '.tshy' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '__image_snapshots__' -type d -exec rm -rf {} +
|
||||
find ./node_modules -name '*.md' -type f -delete
|
||||
find ./node_modules -name '*.markdown' -type f -delete
|
||||
find ./node_modules -name '*~' -type f -delete # Someone forgot some editor buffers, lol
|
||||
find ./node_modules -name 'requirements.txt' -type f -delete
|
||||
find ./node_modules -name 'pyproject.toml' -type f -delete
|
||||
find ./node_modules -name '*.py' -type f -delete
|
||||
find ./node_modules -name '*.sh' -type f -delete
|
||||
find ./node_modules -name '*.bat' -type f -delete
|
||||
find ./node_modules -name '*.cmd' -type f -delete
|
||||
find ./node_modules -name '*.in' -type f -delete
|
||||
find ./node_modules -name '*.mk' -type f -delete
|
||||
find ./node_modules -name '*.txt' -type f -delete
|
||||
find ./node_modules -name '*.Makefile' -type f -delete
|
||||
find ./node_modules -name '*.d.ts' -type f -delete
|
||||
find ./node_modules -name '*.log' -type f -delete
|
||||
find ./node_modules -name '*.tar.gz' -type f -delete
|
||||
find ./node_modules -name '*.cs' -type f -delete
|
||||
find ./node_modules -name '*.rc' -type f -delete
|
||||
find ./node_modules -name '*.am' -type f -delete
|
||||
find ./node_modules -name '*.fallback' -type f -delete
|
||||
find ./node_modules -name '*.msc' -type f -delete
|
||||
find ./node_modules -name '*.1' -type f -delete
|
||||
find ./node_modules -name '*.m4' -type f -delete
|
||||
find ./node_modules -name '*.vc' -type f -delete
|
||||
find ./node_modules -name 'Makefile' -type f -delete
|
||||
find ./node_modules -name 'Dockerfile*' -type f -delete
|
||||
find ./node_modules -name 'tsconfig.*' -type f -delete
|
||||
find ./node_modules -name '.travis.yml' -type f -delete
|
||||
find ./node_modules -name '.prettier*' -type f -delete
|
||||
find ./node_modules -name '.airtap.yml' -type f -delete
|
||||
find ./node_modules -name '.eslintrc' -type f -delete
|
||||
find ./node_modules -name '.eslintrc.yml' -type f -delete
|
||||
find ./node_modules -name '.gitattributes' -type f -delete
|
||||
find ./node_modules -name '.npmignore' -type f -delete
|
||||
find ./node_modules -name '.nycrc' -type f -delete
|
||||
find ./node_modules -name '.editorconfig' -type f -delete
|
||||
find ./node_modules -name '.eslintignore' -type f -delete
|
||||
find ./node_modules -name 'yarn.lock' -type f -delete
|
||||
find ./node_modules -name 'CODEOWNERS' -type f -delete
|
||||
find ./node_modules -name 'README' -type f -delete
|
||||
find ./node_modules -name 'changelog' -type f -delete
|
||||
find ./node_modules -name '*.stflow' -type f -delete
|
||||
find ./node_modules -name '.docker*' -type f -delete
|
||||
find ./node_modules -name 'deno.lock' -type f -delete
|
||||
find ./node_modules -name 'configure' -type f -delete
|
||||
time (
|
||||
echo "Removing random common files..."
|
||||
echo -en "\n - other: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*(\.(github|idea|devcontainer)|tests?|docs?|examples?)$' -type d -exec rm -rf {} + -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*(__image_snapshots__|__snapshots__|__tests__|__fixtures__)$' -type d -exec rm -rf {} + -printf .
|
||||
find ./node_modules -name '.tshy' -type d -exec rm -rf {} + -printf .
|
||||
echo -en "\n - scripts: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(sh|cmd|bat|makefile|mk)$' -type f -delete -printf .
|
||||
find ./node_modules -iname 'makefile' -type f -delete -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(in|py)$' -type f -delete -printf .
|
||||
echo -en "\n - package locks: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*(yarn\.lock|deno-lock\.json|deno\.lock|deno\.jsonc)$' -type f -delete -printf .
|
||||
echo -en "\n - ignore files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(docker|git|npm|eslint|prettier)ignore$' -type f -delete -printf .
|
||||
echo -en "\n - git metadata: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.git(keep|attributes|modules)$' -type f -delete -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*(codeowners|changelog)$' -type f -delete -printf .
|
||||
echo -en "\n - README files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*readme(\.md|\.txt)?$' -type f -delete -printf .
|
||||
find ./node_modules -iname 'readme' -type f -delete -printf .
|
||||
echo -en "\n - RC files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(babel|eslint|prettier|npm|nvm|swc|stylelint|mocha|jshint|nyc|yarn|ncurc)rc(\.(yml|json|(m|c)?js))?$' -type f -delete -printf .
|
||||
echo -en "\n - image files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(png|jpg|jpeg|gif|svg|ico|webp|bmp|tiff)$' -type f -delete -printf .
|
||||
echo -en "\n - text files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(txt|rst|log|md|markdown|hbs|bnf)$' -type f -delete -printf .
|
||||
echo -en "\n - IDE/editor config/buffer files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*(\.(swp|swo|eslintcache)|~)$' -type f -delete -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(vscode|editorconfig|pre-commit-config\.yaml)$' -type f -delete -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(vscode|idea)$' -type d -exec rm -rf {} + -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.jsdoc-conf\.json$' -type d -exec rm -rf {} + -printf .
|
||||
find ./node_modules -iname '*.iml' -type f -delete -printf .
|
||||
echo -en "\n - CI configuration files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*(travis|circleci|github|gitlab|airtap|appveyor|wercker|codeship|drone|semaphoreci|buildkite).*\.(yml|yaml)$' -type f -delete -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.runkit_example\.js$' -type d -exec rm -rf {} + -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*dockerfile.*' -type f -delete -printf .
|
||||
echo -en "\n - TypeScript meta files: "
|
||||
find ./node_modules -iname '*.tsbuildinfo' -type f -delete -printf .
|
||||
find ./node_modules -iname 'tsconfig.json' -type f -delete -printf .
|
||||
echo -en "\n - YAML/TOML/HTML/CSS files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(html|yml|yaml|toml|css)$' -type f -delete -printf .
|
||||
echo -en "\n - Non-normalised JS files (ie. umd/amd/...): "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(amd|umd|browser|web)\.(cjs|mjs|js)$' -type f -delete -printf .
|
||||
echo -en "\n - Test/spec JS files: "
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(test|spec)\.(m|c)?js$' -type f -delete -printf .
|
||||
find ./node_modules -regextype posix-extended -iregex '.*\.(conf|config)\.(m|c)?js$' -type f -delete -printf .
|
||||
)
|
||||
|
||||
if false; then
|
||||
if true; then
|
||||
# Probably dont do this, lol, only saves ~1M anyways
|
||||
# Purely for statistical purposes
|
||||
find ./node_modules -name 'LICENSE' -type f -delete
|
||||
find ./node_modules -name 'License' -type f -delete
|
||||
find ./node_modules -name 'license' -type f -delete
|
||||
find ./node_modules -name 'license.terms' -type f -delete
|
||||
find ./node_modules -name 'LICENSE.txt' -type f -delete
|
||||
find ./node_modules -name 'LICENSE.BSD' -type f -delete
|
||||
find ./node_modules -name 'LICENSE.MIT' -type f -delete
|
||||
find ./node_modules -name 'LICENSE.APACHE2' -type f -delete
|
||||
find ./node_modules -name 'LICENSE-MIT.txt' -type f -delete
|
||||
echo -en "\nRemoving license files: "
|
||||
find ./node_modules -iname 'LICENSE' -type f -delete -printf .
|
||||
find ./node_modules -iname 'license.terms' -type f -delete -printf .
|
||||
find ./node_modules -iname 'LICENSE.txt' -type f -delete -printf .
|
||||
find ./node_modules -iname 'LICENSE.BSD' -type f -delete -printf .
|
||||
find ./node_modules -iname 'LICENSE.MIT' -type f -delete -printf .
|
||||
find ./node_modules -iname 'LICENSE.APACHE2' -type f -delete -printf .
|
||||
find ./node_modules -iname 'LICENSE-MIT.txt' -type f -delete -printf .
|
||||
find ./node_modules -iname 'LICENSE-MIT' -type f -delete -printf .
|
||||
find ./node_modules -iname '*LICENSE*' -type f -delete -printf .
|
||||
find ./node_modules -iname '*LICENCE*' -type f -delete -printf .
|
||||
fi
|
||||
|
||||
echo "Removing empty directories..."
|
||||
find node_modules -maxdepth 1 -type d -empty -delete
|
||||
echo "Trimming complete."
|
||||
time (
|
||||
echo -en "\nReplacing all dotenv transitive dependencies with own version: "
|
||||
find ./node_modules -regextype posix-extended -iregex '\./node_modules/.*/node_modules/dotenv' -type d | while read -r dir; do
|
||||
echo -n .
|
||||
echo "Replacing $dir"
|
||||
rm -rf "$dir"
|
||||
relpath=$(realpath --relative-to="$(dirname "$dir")" ./node_modules/dotenv)
|
||||
ln -s "$relpath" "$dir"
|
||||
done
|
||||
)
|
||||
|
||||
echo -en "\nRemoving empty directories: "
|
||||
find ./node_modules -maxdepth 10 -type d -empty -delete -printf .
|
||||
echo -e "\nTrimming complete. Stats:"
|
||||
du -sh ./{,.}* . 2>/dev/null | sort -h
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env dotnet
|
||||
#:property Nullable=enable
|
||||
#:property PublishAOT=false
|
||||
#:package ArcaneLibs@1.0.0-preview.20251207*
|
||||
|
||||
using ArcaneLibs;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
if(args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("Usage: countExts [options] <directory_path>");
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine(" --size Sort by total size per extension (descending)");
|
||||
Console.WriteLine(" --real-size Sort by estimated disk usage per extension (descending)");
|
||||
Console.WriteLine(" --count Sort by file count per extension (ascending)");
|
||||
Console.WriteLine(" --name Sort by extension name (ascending)");
|
||||
Console.WriteLine(" --reverse Reverse the sort order");
|
||||
return;
|
||||
}
|
||||
|
||||
// undo chdir by dotnet
|
||||
Environment.CurrentDirectory = Environment.GetEnvironmentVariable("PWD") ?? Environment.CurrentDirectory;
|
||||
|
||||
Dictionary<string, long> dirSizes = [];
|
||||
Dictionary<string, long> dirRealSizes = [];
|
||||
Dictionary<string, int> dirCounts = [];
|
||||
long totalSize = 0;
|
||||
long totalRealSize = 0;
|
||||
|
||||
void GetDirSize(string path)
|
||||
{
|
||||
long dirSize = 0;
|
||||
long realDirSize = 0;
|
||||
foreach (var file in Directory.GetFiles(path)) {
|
||||
var len = new FileInfo(file).Length;
|
||||
dirSize += len;
|
||||
// assuming 4KiB block size
|
||||
realDirSize += ((len + 4095) / 4096) * 4096;
|
||||
}
|
||||
|
||||
// include filesystem entry sizes in real size
|
||||
Glibc.stat(path, out var statbuf);
|
||||
realDirSize += statbuf.st_size;
|
||||
|
||||
totalSize += dirSize;
|
||||
totalRealSize += realDirSize;
|
||||
var dirName = Path.GetFileName(path).ToLower();
|
||||
|
||||
if (!dirCounts.ContainsKey(dirName))
|
||||
dirCounts[dirName] = 0;
|
||||
dirCounts[dirName]++;
|
||||
|
||||
if (!dirSizes.ContainsKey(dirName))
|
||||
dirSizes[dirName] = 0;
|
||||
dirSizes[dirName] += dirSize;
|
||||
|
||||
if (!dirRealSizes.ContainsKey(dirName))
|
||||
dirRealSizes[dirName] = 0;
|
||||
dirRealSizes[dirName] += realDirSize;
|
||||
|
||||
foreach (var dir in Directory.GetDirectories(path)) GetDirSize(dir);
|
||||
}
|
||||
|
||||
GetDirSize(args.First(a=>!a.StartsWith("--")));
|
||||
var extColWidth = dirCounts.Max(k => k.Key.Length) + 1;
|
||||
var numColWidth = dirCounts.Max(k=>k.Value.ToString().Length) + 1;
|
||||
|
||||
IEnumerable<KeyValuePair<string, int>> sortedDirs = dirCounts.OrderByDescending(kvp => kvp.Value);
|
||||
|
||||
if (args.Contains("--size"))
|
||||
sortedDirs = dirCounts.OrderByDescending(kvp => dirSizes[kvp.Key]);
|
||||
if (args.Contains("--real-size"))
|
||||
sortedDirs = dirCounts.OrderByDescending(kvp => dirRealSizes[kvp.Key]);
|
||||
if (args.Contains("--ext"))
|
||||
sortedDirs = dirCounts.OrderBy(kvp => kvp.Key);
|
||||
if (args.Contains("--count"))
|
||||
sortedDirs = dirCounts.OrderBy(kvp => kvp.Value);
|
||||
|
||||
if (args.Contains("--reverse"))
|
||||
sortedDirs = sortedDirs.Reverse();
|
||||
|
||||
if (args.Contains("--duplicate-only"))
|
||||
sortedDirs = sortedDirs.Where(kvp => kvp.Value > 1);
|
||||
|
||||
foreach (var kvp in sortedDirs) Console.WriteLine($"{kvp.Value.ToString().PadLeft(numColWidth)} {kvp.Key.PadRight(extColWidth)} Total Size: {Util.BytesToString(dirSizes[kvp.Key]).PadRight(12)} Est. usage: {Util.BytesToString(dirRealSizes[kvp.Key])}");
|
||||
|
||||
Console.WriteLine($"\nTotal unique directory names: {dirCounts.Count}");
|
||||
Console.WriteLine($"Total disk usage: {Util.BytesToString(totalSize)} (est. usage: {Util.BytesToString(totalRealSize)})");
|
||||
|
||||
static class Glibc
|
||||
{
|
||||
// to get filesystem entry size for directories
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int stat(string path, out Stat buf);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Stat
|
||||
{
|
||||
public ulong st_dev;
|
||||
public ulong st_ino;
|
||||
public ulong st_nlink;
|
||||
public uint st_mode;
|
||||
public uint st_uid;
|
||||
public uint st_gid;
|
||||
public ulong st_rdev;
|
||||
public long st_size;
|
||||
public long st_blksize;
|
||||
public long st_blocks;
|
||||
public long st_atime;
|
||||
public ulong st_atime_nsec;
|
||||
public long st_mtime;
|
||||
public ulong st_mtime_nsec;
|
||||
public long st_ctime;
|
||||
public ulong st_ctime_nsec;
|
||||
public long __unused1;
|
||||
public long __unused2;
|
||||
public long __unused3;
|
||||
}
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env dotnet
|
||||
#:property Nullable=enable
|
||||
#:property PublishAOT=false
|
||||
#:package ArcaneLibs@1.0.0-preview.20251207*
|
||||
|
||||
using ArcaneLibs;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
if(args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("Usage: countExts [options] <directory_path>");
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine(" --size Sort by total size per extension (descending)");
|
||||
Console.WriteLine(" --real-size Sort by estimated disk usage per extension (descending)");
|
||||
Console.WriteLine(" --ext Sort by extension name (ascending)");
|
||||
Console.WriteLine(" --count Sort by file count per extension (ascending)");
|
||||
Console.WriteLine(" --by-filename Use full filename instead of extension for counting");
|
||||
Console.WriteLine(" --double-ext Consider double extensions (e.g., .test.js)");
|
||||
Console.WriteLine(" --filename-fallback Use full filename as extension if no extension found");
|
||||
return;
|
||||
}
|
||||
|
||||
// undo chdir by dotnet
|
||||
Environment.CurrentDirectory = Environment.GetEnvironmentVariable("PWD") ?? Environment.CurrentDirectory;
|
||||
|
||||
Dictionary<string, int> extCounts = [];
|
||||
Dictionary<string, long> extSizes = [];
|
||||
Dictionary<string, long> extRealSizes = [];
|
||||
long totalSize = 0;
|
||||
long totalRealSize = 0;
|
||||
|
||||
void CountExtensions(string path)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(path))
|
||||
{
|
||||
string ext = args.Contains("--by-filename") ? Path.GetFileName(file).ToLower() : Path.GetExtension(file).ToLower();
|
||||
|
||||
// handle double extensions, ie. .test.js, .min.js etc
|
||||
if (args.Contains("--double-ext") && Path.GetFileName(file).Count(c => c == '.') >= 2)
|
||||
{
|
||||
var fname = Path.GetFileNameWithoutExtension(file);
|
||||
var secondExt = Path.GetExtension(fname).ToLower();
|
||||
if (!string.IsNullOrEmpty(secondExt))
|
||||
ext = secondExt + ext;
|
||||
}
|
||||
|
||||
if(string.IsNullOrEmpty(ext))
|
||||
ext = args.Contains("--filename-fallback") ? Path.GetFileName(file).ToLower() : "<no_ext>";
|
||||
|
||||
if (!extCounts.ContainsKey(ext))
|
||||
extCounts[ext] = 0;
|
||||
extCounts[ext]++;
|
||||
|
||||
var fi = new FileInfo(file);
|
||||
if (!extSizes.ContainsKey(ext))
|
||||
extSizes[ext] = 0;
|
||||
extSizes[ext] += fi.Length;
|
||||
totalSize += fi.Length;
|
||||
|
||||
// Assuming 4KiB block size
|
||||
if (!extRealSizes.ContainsKey(ext))
|
||||
extRealSizes[ext] = 0;
|
||||
extRealSizes[ext] += (((fi.Length + 4095) / 4096) * 4096);
|
||||
totalRealSize += (((fi.Length + 4095) / 4096) * 4096);
|
||||
}
|
||||
|
||||
foreach (var dir in Directory.GetDirectories(path)) CountExtensions(dir);
|
||||
}
|
||||
|
||||
CountExtensions(args.First(a=>!a.StartsWith("--")));
|
||||
var extColWidth = extCounts.Max(k => k.Key.Length) + 1;
|
||||
var numColWidth = extCounts.Max(k=>k.Value.ToString().Length) + 1;
|
||||
|
||||
var sortedExts = extCounts.OrderByDescending(kvp => kvp.Value);
|
||||
|
||||
if (args.Contains("--size"))
|
||||
sortedExts = extCounts.OrderByDescending(kvp => extSizes[kvp.Key]);
|
||||
if (args.Contains("--real-size"))
|
||||
sortedExts = extCounts.OrderByDescending(kvp => extRealSizes[kvp.Key]);
|
||||
if (args.Contains("--ext"))
|
||||
sortedExts = extCounts.OrderBy(kvp => kvp.Key);
|
||||
if (args.Contains("--count"))
|
||||
sortedExts = extCounts.OrderBy(kvp => kvp.Value);
|
||||
|
||||
foreach (var kvp in sortedExts) Console.WriteLine($"{kvp.Value.ToString().PadLeft(numColWidth)} {kvp.Key.PadRight(extColWidth)} Total Size: {Util.BytesToString(extSizes[kvp.Key]).PadRight(12)} Est. usage: {Util.BytesToString(extRealSizes[kvp.Key])}");
|
||||
|
||||
Console.WriteLine($"\nTotal unique extensions: {extCounts.Count}");
|
||||
Console.WriteLine($"Total disk usage: {Util.BytesToString(totalSize)} (est. usage: {Util.BytesToString(totalRealSize)})");
|
||||
Reference in new issue
Block a user