lsr – Das fehlende Listing

Ob Prozesse, offene Ports, Benutzer, Netzwerkverbindungen, Hardware oder Dateien: auf die richtige Auflistung kommt es immer an. Doch häufig werden die Ausgaben von ls recht lang. Da hilft nur der richtige Filter.

Für Dateinamen oder manche Eigenschaften bieten die globs der verbreiteten shells komfortable Möglichkeiten. Die Liste der Verzeichnisse im aktuellen Pfad zum Beispiel liefert die Ausgabe von

ls -d */

Doch schon schnell gelangt man an die Grenzen der globs und greift zum nächsten Werkzeug. Das ist in den meisten Fällen find. Damit lassen sich zum Beispiel Dateien nach den drei Zeitstempeln (creation, modification, access) filtern.

find . -maxdepth 1 -ctime +30

liefert die Liste der mindestens 30 Tage alten Dateien des aktuellen Verzeichnesses. Aber ein Werkzeug, um Dateien nach den Rechten des aktuellen Benutzers auszusuchen habe ich nicht gefunden. Im Kopf begann ich schon den find-Aufruf zu überlegen, als ich mich an die glob qualifiers der zsh erinnerte. Glob qualifiers sind im Prinzip weitere Optionen, die bei der Generierung von Dateinamen ausgewertet werden. Zu den einfachen Vertretern dieser Gattung gehört das Zeichen @, das die Auswahl auf symbolische Links einschränkt:

ls -d *(@)

Aber auch Besitzer und Berechtigungen einer Datei lassen sich ausdrücken. Die benutzten Ausdrücke waren jeder für sich relativ einfach:

  • world readable: *(R)
  • lesbar durch User $LOGNAME: *(ru:$LOGNAME:)
  • lesbar durch Gruppe $gruppe: *(Ag:$gruppe:)

Die zusammen benutzten glob qualifiers schränken die Auswahl immer weiter ein. Um also zwei Bedingungen mit einem oder zu verknüpfen schreibt man einfach zwei globs hintereinander. Das bedeutet aber, dass eine Datei, auf die beide globs zutreffen auch zwei Male im Gesamtausdruck steht. Der einfachste Aufruf wäre also absolut unübersichtlich:

ls -d *(R) *(ru:$LOGNAME:) $(for g in $(groups); do print -r “*(Ag:$g:)”; done)

Also schrieb ich einen weiteren Ausdruck dazu. Zuerst füllte ich ein Array mit sämtlichen Dateien aller globs und benutzte dann die parameter expansion, um die Liste zu kürzen:

files=( *(R) *(ru:$LOGNAME:) $(for g in $(groups); do print -r “*(Ag:$g:)”; done) )
ls -d ${(u)files}

Zuletzt galt es nur noch die unzutreffenden globs zu entfernen. Das normale Verhalten der zsh ist, bei jedem glob, der auf keine Datei zutrifft, eine entsprechende Meldung auszugeben. Das ist bei dieser Benutzung äußerst störend, wird aber durch einen weiteren glob qualifier deaktiviert. Der Operator N setzt die Option NULL_GLOB für den betroffenen Ausdruck, falls dieser also keine passenden Dateien hat, wird er als leerer String gewertet.

files=( *(NR) *(Nru:$LOGNAME:) $(for g in $(groups); do print -r “*(NAg:$g:)”; done) )
ls -d ${(u)files}

Die fertige Funktion ist vom Aufruf möglichst ähnlich zu ls und liegt hier.


Über diesen Beitrag


Hinterlasse einen Kommentar

XHTML: Folgende Tags sind erlaubt: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>




Safari hates me