Michael Wesemann 659ab03652 [mike@maginot]
2026-08-10 19:17:03 +02:00
2026-08-10 16:35:51 +02:00
2026-08-10 16:35:51 +02:00
2026-08-10 16:35:51 +02:00
2026-08-10 19:17:03 +02:00
2026-08-10 19:17:03 +02:00
2026-08-10 19:17:03 +02:00
2026-08-10 19:17:03 +02:00

dx

Zählt, was in einem Verzeichnis liegt, und wie schwer es ist — eine Ebene tief, ein Blick, sofort fertig.

$ dx ~/src -r -t 8
/Users/mike/src        2489     1.1G
  Wetter/               297     316M  ██▉         29%
  gblog/                 99     135M  █▎          12%
  gbld/                  82     131M  █▏          12%
  goca/                  80     108M  █           10%
  futterturm/            62      68M  ▋            6%
  BugSim/               323      68M  ▋            6%
  gvm/                   37      57M  ▌            5%
  mJournal/             204      42M  ▍            4%
  … 16 more            1305     179M  █▋          16%

Links der Name, dann die Zahl der enthaltenen Dateien, dann die Summe ihrer Größen, dann der Anteil am Ganzen. Die Kopfzeile ist das Verzeichnis selbst. Verzeichnisse werden vollständig durchlaufen, aber nicht aufgeklappt — für alles Weitere ist ncdu da.

Im Terminal ist die Ausgabe farbig, nach der Palette aus mwxcol.

Bauen und installieren

cd ~/src/dx
./build.sh
cp bin/dx ~/bin/dx

build.sh baut nach ./bin, je ein Binary für macOS und Linux auf arm64 und amd64, und legt bin/dx als Symlink auf das für diese Maschine. Für eine einzelne Plattform:

PLATFORMS="linux/amd64" ./build.sh

Jeder Lauf zählt die Patch-Nummer in version.txt um eins hoch und baut sie per -ldflags in alle Binaries ein — dx --version sagt also, welcher Bau läuft. Ein nacktes go build geht auch, meldet dann aber die Vorgabe aus main.go statt der wirklichen Nummer.

Braucht Go ≥ 1.26 und github.com/fatih/color. Das Perl-Original (dx, 1.0.2, 2016) liegt unverändert daneben und wird vom Bau nicht angefasst; es hat keine Farben und keine Balken, tut aber sonst dasselbe.

Selbst aktualisieren

dx --check-update   # nur nachsehen
dx --update         # holen und ersetzen

dx holt sich das neueste Release von git.micw.org/mike/dx — die URL steht fest im Programm, es gibt nichts zu konfigurieren. Gebraucht wird ein Release je Version, dessen Tag die nackte Nummer ist (2.1.6), mit den Dateien aus ./bin als Assets; gesucht wird die eine, die zu GOOS/GOARCH dieser Maschine passt.

Ersetzt wird die laufende Datei selbst. Ist der aufgerufene dx ein Symlink — etwa ~/bin/dx auf ~/src/dx/bin/dx-darwin-arm64 —, wird das Ziel dahinter erneuert, nicht der Link. Vor dem Tausch wird das frisch Geladene einmal mit --version aufgerufen; meldet es nicht die erwartete Nummer, bleibt alles, wie es war. Der Tausch selbst ist ein rename im selben Verzeichnis, also atomar: entweder die alte Datei oder die neue, nie eine halbe.

Liegt das Binary irgendwo, wo der eigene Benutzer nicht schreiben darf (/usr/local/bin), sagt dx --update das und tut nichts — dann sudo.

Wiederverwenden

selfupdate.go hängt an nichts im Rest des Programms und kommt mit der Standardbibliothek aus. Für ein anderes Programm die Datei kopieren, den Block oben anpassen —

var selfUpdate = selfUpdater{
	repo:    "https://git.micw.org/mike/foo",
	asset:   "foo",
	current: version,
	verify:  []string{"--version"},
}

— und --update und --check-update in die Optionen hängen. Alles Weitere in der Datei heißt selfUpdate… oder update… und kollidiert deshalb nicht. verify leer lassen, wenn das Programm keinen billigen Versionsaufruf hat; dann entfällt der Probelauf. Erwartet wird eine Gitea-Instanz (getestet mit 1.27); GitHub kennt dieselbe Route unter anderen Feldnamen und wird nicht bedient.

Optionen

-n --number nach Dateizahl sortieren statt nach Größe
-d --dirs nur Verzeichnisse zählen, Dateien der obersten Ebene weglassen
-r --reverse größtes zuerst
-t N --top=N nur die N größten zeigen, den Rest zu einer Zeile summieren
-h --help Hilfe
--bar, --no-bar Balken und Prozent erzwingen bzw. abschalten
--color=auto|always|never Farbe erzwingen bzw. abschalten
--version Version
--check-update nachsehen, ob ein neueres Release da ist
--update neuestes Release holen und installieren

Kurzoptionen lassen sich bündeln (-rt 3, -dn), der Wert von -t darf kleben (-t5) oder folgen (-t 5). Ein -- trennt Optionen von einem Pfad, der mit - beginnt. Ohne Pfad gilt das aktuelle Verzeichnis.

Sortiert wird aufsteigend, das Größte steht also direkt über dem Prompt und man muss nicht scrollen. -r dreht das um, für Pipes und lange Listen.

Bei -t steht die Sammelzeile immer am kleinen Ende: oben bei normaler Sortierung, unten bei -r.

Exit
0 alles gelesen
1 Pfad existiert nicht oder ist kein Verzeichnis
2 Option falsch benutzt

Farbe und Balken

Beides gilt am Terminal und entfällt in einer Pipe — dx | sort bekommt reinen Text. --color=always schaltet beides wieder ein, für less -R. Wer nur eins davon will, sagt es mit --bar / --no-bar ausdrücklich. NO_COLOR wird beachtet.

Die Farben folgen den file_type-Rollen aus themes/eza/theme.yml, damit dieselbe Datei in eza und dx gleich aussieht:

Verzeichnis blue, fett Archive orange
ausführbar green, fett Bilder violet
Symlink pink Video pink
Quelltext, Konfiguration blue Audio green
README, Makefile, go.mod yellow Schlüssel, Zertifikate red
Dokumente white Kompilate (.o, .dylib) grey
sonstige Dateien white .tmp, .bak, .DS_Store darker

Die Zahlenspalte ist grey, eine Null dark. Die Größenspalte trägt die Größenrampe des eza-Themes — bis K green, M yellow, G orange, T red — und der Balken nimmt die Farbe der Spalte auf, deren Anteil er zeigt: die der Größe, mit -n die der Dateizahl.

Der Balken ist zehn Zellen breit und rechnet in Achteln (▏▎▍▌▋▊▉█). Was weniger als ein halbes Prozent ausmacht, bekommt keinen Strich und steht als <1% da statt als geschöntes 0%. Dadurch bleiben genau die Zeilen sichtbar, auf die es ankommt.

Größen

Die Schwellen sind die des Originals: ab 1024 der jeweiligen Einheit wird umgeschaltet. Unterhalb von 10 kommt eine Nachkommastelle dazu, weil 2G sonst alles zwischen 1,5 und 2,4 Gigabyte bedeuten könnte. Ganze Bytes bleiben ganz.

8   4.9K   316M   1.1G

Was genau gezählt wird

Gezählt werden reguläre Dateien, wie bei find -type f. Verzeichnisse, Sockets, Fifos und Geräte zählen nicht mit, auch nicht die Verzeichnisse selbst.

  • Ein Symlink auf ein Verzeichnis wird nicht verfolgt und steht deshalb mit 0 da — pink eingefärbt, damit die Null erklärt ist.
  • Ein Symlink auf eine Datei auf oberster Ebene zählt mit der Größe seines Ziels, ebenfalls pink.
  • Hardlinks zählen so oft, wie sie vorkommen. In einem Baum mit rsync --link-dest oder Time Machine sind die Zahlen dadurch zu hoch; für so etwas ist dx nicht gedacht.
  • Gemessen wird die Dateigröße, nicht der belegte Platz. Sparse-Dateien und APFS-Klone erscheinen größer, als sie auf der Platte sind.
  • Was sich nicht lesen lässt — gesperrte Verzeichnisse, tote Symlinks — wird übersprungen und am Ende auf stderr gemeldet, damit die Tabelle heil bleibt.
  • -d lässt Dateien der obersten Ebene ganz weg, auch aus der Summe.

Unterverzeichnisse werden nebenläufig durchlaufen, so viele auf einmal wie Kerne da sind. Das Original startete pro Verzeichnis einen find-Prozess; auf ~/go sind das 0,19 s statt 0,34 s.

Unterschiede zum Perl-Original

  1. Gleichstände sortieren nach Namen. Perl ließ sie in der Reihenfolge des Hashes, dx -n gab bei jedem Aufruf eine andere Reihenfolge aus.
  2. Ein ungültiger Pfad ist ein Fehler. Perl listete stillschweigend das aktuelle Verzeichnis — plausible, aber falsche Zahlen.
  3. Die Namensspalte ist eine Stelle breiter, wenn der längste Eintrag ein Verzeichnis ist. Perl zählte den angehängten / bei der Spaltenbreite nicht mit, der längste Name klebte am Zahlenblock.
  4. Fehler stehen auf stderr, statt als find: … Permission denied mitten in der Ausgabe.
  5. Größen haben eine Nachkommastelle, siehe oben. Das ist die einzige Abweichung im alten Ausgabeformat; ohne Farbe und Balken ist der Rest byteweise identisch.

Neu sind -r, -t, die Balkenspalte, die Farben und die langen Optionen.

Aufbau

Datei
main.go Zählen, Sortieren, Formatieren, Optionen
filetypes.go Endung und Dateiname → Farbe
selfupdate.go --update, eigenständig und zum Kopieren gedacht
build.sh Bau für alle Plattformen, zählt version.txt hoch
version.txt die zuletzt gebaute Version
dx das Perl-Original von 2016

Die Palette steht in main.go doppelt — einmal als Zahlenwerte, einmal in den Kommentaren als Rolle. Quelle der Wahrheit bleibt ~/src/mwxcol/mwxcol.go; ändert sie sich dort, müssen die elf rgb{…} hier nachgezogen werden.

S
Description
No description provided
Readme 52 KiB
2.1.8 Latest
2026-08-10 19:17:56 +02:00
Languages
Go 92.5%
Shell 7.5%