Primeiro, como um formato stat , "% Sdr" é interpretado como o seletor de campo d
, modificado pelo especificador S
, seguido por um caractere literal de letra minúscula. / p>
A manpage provavelmente seria mais clara se dissesse "d, r" em vez de "dr" sob a descrição de S
. d
e r
são ambos seletores de campo separados. r
seleciona o número do dispositivo a partir da informação stat (2) (isto é, st_rdev; útil apenas para entradas de dispositivos estatísticos (ou seja, as entradas em / dev)). d
seleciona o número do dispositivo que contém a entrada da estatística (ou seja, st_dev). O número impresso é uma combinação dos números principal e secundário mostrados por ls (maior
S
é um modificador que pode ser aplicado a d
, r
e vários outros seletores de campo. Quando aplicado a d
ou r
, ele tenta imprimir o nome do dispositivo em vez de seu número bruto. Alguns dispositivos, como os dispositivos do sistema de arquivos virtual, não possuem nomes próprios, portanto, imprime ???
(pode ser melhor se ele imprimiu <major>,<minor>
). Isso não significa que esses sistemas de arquivos não possuam dispositivos, apenas que seus dispositivos não possuem nomes normais como "disk0s3".
A "estranheza do shell" ("subconjunto aparentemente arbitrário de arquivos do CWD") é devido à falta de cotação. O shell vê o (sem aspas) "???" resultar e expande-lo como um padrão glob. Se o cwd contiver alguma entrada com exatamente três bytes (caracteres, dependendo da localidade?), O shell substituirá essas entradas pelo padrão glob. O comportamento (a cotação e a expansão glob) varia por shell e geralmente pode ser modificado por várias opções de shell.
Você pode modificar seu comando original assim para evitar a globbing e o "r":
df | grep -e/ | awk '{print $NF}' | while read line; do echo "$line" "$(stat -f%Sd "$line"); done
Mas eu provavelmente escreveria assim:
df | tail +2 | awk '{print $NF}' | xargs stat -f'%N %Sd %d'
- Observe que isso falha para que qualquer sistema de arquivos montado tenha espaços em seus nomes de ponto de montagem. Nem a saída de mount ou df é super fácil de analisar prontamente (ambos têm campos que podem ter sequências quase arbitrárias neles).
Com essa saída (nome, número do dispositivo, nome do dispositivo), talvez você possa ter uma ideia melhor do que está acontecendo.
Ou talvez você queira ver os números principais e secundários além dos números de dispositivos brutos (compare com o que você vê em (por exemplo) ls -l /dev/disk0s3
):
df | tail +2 | awk '{print $NF}' | xargs stat -f'%N %Sd %d' |
awk 'BEGIN{f=2^24} {$(NF+1) = int($NF/f) "," ($NF%f) } 1'
Aqui está um pequeno programa em C que pode substituir o pipeline problemático "df | head | awk".
Naturalmente, esse programa em C pode fazer o resto funcionar sozinho, mas pode ser bom ter um programa autônomo que possa simplesmente criar pontos de montagem terminados em NUL.
mountz | xargs -0 stat -f'%N %Sd %d' |
awk 'BEGIN{f=2^24} {$(NF+1) = int($NF/f) "," ($NF%f) } 1'
Código:
#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);
}
}