Erstens, als ein STAT - Format, „% Sdr“ als interpretierte d
Feldwähler, durch die modifizierten S
Spezifizierer, gefolgt von einem wörtlichen Klein R Charakter.
Die Manpage wäre wahrscheinlich klarer, wenn unter der Beschreibung von "d, r" anstelle von "dr" steht S
. d
und r
sind beide separate Feldselektoren. r
wählt die Gerätenummer aus der stat (2) -Info aus (dh st_rdev; nur nützlich bei der Registrierung von Geräteeinträgen (dh den Einträgen unter / dev)). d
Wählt die Gerätenummer des Geräts aus, das den angegebenen Eintrag enthält (dh st_dev). Die Zahl, die gedruckt wird, ist eine Kombination der Haupt- und Nebenzahlen, die durch ls (Haupt << 24 | Minor) angezeigt werden .
S
ist ein Modifikator, der auf beiden angewandt werden kann d
, r
und mehr anderen Feld Selektoren. Bei der Anwendung auf d
oder r
wird versucht, den Namen des Geräts anstelle der Rohnummer zu drucken. Einige Geräte, wie die virtuellen Dateisystemgeräte, haben keine richtigen Namen, so dass sie ???
stattdessen gedruckt <major>,<minor>
werden. Dies bedeutet nicht, dass diese Dateisysteme keine Geräte haben, nur dass ihre Geräte keine normalen Namen wie "disk0s3" haben.
Die "Shell Weirdness" ("scheinbar willkürliche Untermenge der Dateien von CWD") ist auf fehlende Zitate zurückzuführen. Die Shell sieht das (nicht zitierte) "???" Ergebnis und erweitert es als Glob-Muster. Wenn der cwd Einträge mit genau drei Bytes enthält (Zeichen abhängig vom Gebietsschema?), Ersetzt die Shell diese Einträge für das Glob-Muster. Das Verhalten (das Zitieren und die Glob-Erweiterung) variiert je nach Shell und kann normalerweise durch verschiedene Shell-Optionen geändert werden.
Sie können Ihren ursprünglichen Befehl wie folgt modifizieren, um das Glätten und das nachfolgende "r" zu vermeiden:
df | grep -e/ | awk '' | while read line; do echo "$line" "$(stat -f%Sd "$line"); done
Aber ich würde es wahrscheinlich stattdessen so schreiben:
df | tail +2 | awk '' | xargs stat -f'%N %Sd %d'
- Beachten Sie, dass dies für alle angehängten Dateisysteme fehlschlägt, die Leerzeichen in ihren Mountpunktnamen enthalten. Weder die Ausgabe von mount noch df ist sehr einfach zu parsen (beide haben Felder, die fast beliebige Zeichenketten enthalten).
Mit dieser Ausgabe (Name, Gerätenummer, Gerätename) erhalten Sie möglicherweise eine bessere Vorstellung davon, was los ist.
Oder möchten Sie vielleicht zusätzlich zu den unformatierten Gerätenummern die Haupt- und Minor-Nummern sehen (vergleichen Sie diese mit dem, was Sie in (zB) sehen ls -l /dev/disk0s3
):
df | tail +2 | awk '' | xargs stat -f'%N %Sd %d' | awk 'BEGIN {$(NF+1) = int($NF/f) "," ($NF%f) } 1'
Hier ist ein kleines C-Programm, das die problematische "df | head | awk" -Pipeline ersetzen kann.
Natürlich kann ein solches C-Programm die restliche Arbeit selbst erledigen, aber es wäre vielleicht schön, ein eigenständiges Programm zu haben, das nur NUL-terminierte Mountpunkte ausspucken kann.
mountz | xargs -0 stat -f'%N %Sd %d' | awk 'BEGIN {$(NF+1) = int($NF/f) "," ($NF%f) } 1'
Code:
#include <sys/mount.h> #include <stdio.h> #include <stdlib.h> /* usage: mountz | xargs -0 command_for_each_mount_point */ int main(int argc, const char *argv[]) { struct statfs *buf; int flags = MNT_NOWAIT, num_fs, num_stat, i; unsigned bufsz; num_fs = getfsstat(NULL, 0, flags); if (num_fs < 0) { perror("unable to count mounted filesystems: getfsstat"); exit(1); } bufsz = sizeof(*buf) * num_fs; buf = malloc(bufsz); if (!buf) { perror("unable to allocate %u statfs structs"); exit(1); } fprintf(stderr, "p=%p\n", buf); num_stat = getfsstat(buf, bufsz, flags); if (num_stat < 0) { perror("unable to getfsstat"); exit(1); } if (num_stat != num_fs) { fprintf(stderr, "Hmm, expected %u, got %d.\n", num_fs, num_stat); } for (i = 0; i < num_stat; i++) { fprintf(stdout, "%s%c", buf[i].f_mntonname, 0); } }