d_type
è un'ottimizzazione della velocità per risparmiare su lstat(2)
chiamate, quando è supportato.
Come il readdir
(3) la pagina man sottolinea che non tutti i filesystem restituiscono informazioni reali nel d_type
field (tipicamente perché ci vorrebbe una ricerca su disco extra per leggere l'inode, come nel caso di XFS se non hai usato mkfs.xfs -n ftype=1
(implicito da -m crc=1
che non è ancora l'impostazione predefinita). Filesystem che impostano sempre DT_UNKNOWN
sono comuni nella vita reale e non qualcosa che puoi ignorare. XFS non è l'unico esempio.
Hai sempre bisogno di un codice che ripieghi sull'utilizzo di lstat
(2) se d_type==DT_UNKNOWN
, se il nome del file da solo non è sufficiente per decidere che non è interessante. (Questo è il caso di alcuni chiamanti, come find -name
o globi in espansione come *.c
, motivo per cui readdir
non comporta il sovraccarico di compilarlo se richiederebbe una lettura extra del disco.)
Il Linux getdents(2)
la pagina man ha un programma di esempio che fa quello che stai cercando di fare, incluso un blocco operatore ternario concatenato per decodificare il d_type
campo in stringhe di testo. (Come sottolineano le altre risposte, il tuo errore è stamparlo come carattere, piuttosto che confrontarlo con DT_REG
, DT_DIR
, ecc.)
Ad ogni modo, le altre risposte coprivano principalmente cose, ma mancavano i dettagli critici che HAI BISOGNO di un fallback per il caso in cui d_type == DT_UNKNOWN
(0 su Linux. d_type
è memorizzato in quello che era un byte di riempimento, fino a Linux 2.6.4).
Per essere portabile, il tuo codice deve verificare che struct dirent
ha anche un d_type
campo, se lo usi, o il tuo codice non verrà nemmeno compilato al di fuori dei sistemi GNU e BSD. (vedi readdir(3)
)
Ho scritto un esempio per trovare directory con readdir , utilizzando d_type
con un fallback a stat
quando d_type non è disponibile in fase di compilazione, quando è DT_UNKNOWN e per i collegamenti simbolici.
Il d_type
nella struttura di ritorno fornisce un numero per il tipo. Non puoi stamparlo direttamente perché i valori usati non sono stampabili se interpretati come ASCII (per esempio sono 4 per le directory e 8 per i file.
Puoi stamparli come numeri come questo:
printf("%d ", dent->d_type)
Oppure confrontali con le costanti come DT_DIR
e costruire un output significativo da questo, come un tipo char:
if(dent->type == DT_DIR) type = 'd'
Stampa d_type
come numero intero in questo modo:
printf("%d ", dent->d_type);
e vedrai valori significativi.