enum { DT_UNKNOWN = 0, #define DT_UNKNOWN DT_UNKNOWN //未知的类型 DT_FIFO = 1, #define DT_FIFO DT_FIFO //命名管道或FIFO DT_CHR = 2, #define DT_CHR DT_CHR //字符设备文件 DT_DIR = 4, #define DT_DIR DT_DIR //普通目录 DT_BLK = 6, #define DT_BLK DT_BLK //块设备文件 DT_REG = 8, #define DT_REG DT_REG //普通文件 DT_LNK = 10, #define DT_LNK DT_LNK //快捷方式 DT_SOCK = 12, #define DT_SOCK DT_SOCK //本地套接口 DT_WHT = 14 #define DT_WHT DT_WHT //whiteout }; /* whiteout 概念存在于联合文件系统(UnionFS)中,代表某一类占位符形态的特殊文件, 当用户文件夹与系统文件夹的共通部分联合到一个目录时(例如 bin 目录), 用户可删除归属于自己的某些系统文件副本,但归属于系统级的原件仍存留于同一个联合目录中, 此时系统将产生一份 whiteout 文件,表示该文件在当前用户目录中已删除,但系统目录中仍然保留。 */
可以这些写一个类似于Linux中Tree类似功能的程序,而且貌似st_mode比dtype要判断的精确,误差更小。
stat 返回lnk所指向的文件信息
lstat 返回lnk的信息
其他都一样
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #define PATH_LENGTH 2000 #define FILE_MAXN 1000 #define NAME_LENGTH 255 struct OPT { int Show_Hidden_File; int Show_File; }; void Print_TAB(int Dep) { for (int i = 1; i < Dep; i++) printf("| "); printf("|-- "); } int Is_Hidden_File(const char * Str) { if (Str[0] == '.') return 1; return 0; } //int Reg = 0, Chr = 0, Blk = 0, Sock = 0, Fifo = 0; int Is_File(char * File_Path) { struct stat S_Buf; if (lstat(File_Path, &S_Buf) < 0) return 1; #if 0 if (S_ISREG(S_Buf.st_mode)) Reg++; if (S_ISCHR(S_Buf.st_mode)) Chr++; if (S_ISBLK(S_Buf.st_mode)) Blk++; if (S_ISSOCK(S_Buf.st_mode)) Sock++; if (S_ISFIFO(S_Buf.st_mode)) Fifo++; #endif if (S_ISREG(S_Buf.st_mode) || S_ISCHR(S_Buf.st_mode) || S_ISBLK(S_Buf.st_mode) || S_ISFIFO(S_Buf.st_mode) || S_ISSOCK(S_Buf.st_mode)) return 1; if (S_ISLNK(S_Buf.st_mode)) { if (stat(File_Path, &S_Buf) < 0) return 1; #if 0 if (S_ISREG(S_Buf.st_mode)) Reg++; if (S_ISCHR(S_Buf.st_mode)) Chr++; if (S_ISBLK(S_Buf.st_mode)) Blk++; if (S_ISSOCK(S_Buf.st_mode)) Sock++; if (S_ISFIFO(S_Buf.st_mode)) Fifo++; #endif if (S_ISREG(S_Buf.st_mode) || S_ISCHR(S_Buf.st_mode) || S_ISBLK(S_Buf.st_mode) || S_ISFIFO(S_Buf.st_mode) || S_ISSOCK(S_Buf.st_mode)) return 1; } return 0; } int Is_Dir(char * File_Path) { struct stat S_Buf; stat(File_Path, &S_Buf); if (S_ISDIR(S_Buf.st_mode) || S_ISSOCK(S_Buf.st_mode)) return 1; return 0; } int Is_Lnk(char * File_Path) { struct stat S_Buf; lstat(File_Path, &S_Buf); //!! use lstat if (S_ISLNK(S_Buf.st_mode)) return 1; return 0; } int Cmp(const char * Str1, const char * Str2) { for (int i = 0; Str1[i] && Str2[i]; i++) { if (Str1[i] > Str2[i]) return 1; if (Str1[i] < Str2[i]) return 0; } return 1; } /* 用stat之后结果会准确很多,但是在/proc/self/task这个文件夹下面有个fd的文件夹和一个fdinfo的文件夹, 里面分别有两个软连接,tree只会打开其中一个,我的两个无法打开 */ void Tree_Maker(const char * Cur_Path, int Depth, OPT Opt, int * Dir_Num, int * File_Num) { DIR *dir; struct dirent *node; if ((dir = opendir(Cur_Path)) == NULL) return; /* char File[FILE_MAXN][NAME_LENGTH]; int Cnt = 0; while ((node = readdir(dir)) != NULL) strcpy(File[++Cnt], node->d_name); closedir(dir); for (int i = 1; i <= Cnt; i++) for (int j = i + 1; j <= Cnt; j++) if (Cmp(File[i], File[j])) { char Tmp[PATH_LENGTH]; strcpy(Tmp, File[i]); strcpy(File[i], File[j]); strcpy(File[j], Tmp); } */ while ((node = readdir(dir)) != NULL) { char File_Path[PATH_LENGTH]; strcpy(File_Path, Cur_Path); strcat(File_Path, "/"); strcat(File_Path, node->d_name); int Sym_File = Is_File(File_Path); if (strcmp(node->d_name, ".") == 0 || strcmp(node->d_name, "..") == 0) continue; //Ignore dot and dot-dot if (Is_Hidden_File(node->d_name) && !Opt.Show_Hidden_File) continue; if (Sym_File && !Opt.Show_File) continue; Print_TAB(Depth); printf("%s", node->d_name); if (Sym_File) (*File_Num)++; else { (*Dir_Num)++; //printf("!!!"); } putchar('\n'); if (Is_Dir(File_Path) && !Is_Lnk(File_Path)) Tree_Maker(File_Path, Depth + 1, Opt, Dir_Num, File_Num); } closedir(dir); } int main(int argc, char* argv[]) { if (argc > 3) { puts("参数过多"); return -1; } OPT Opt = { 0,1 }; char Path[PATH_LENGTH] = "."; if (argc == 2) { if (argv[1][0] == '-') { if (strcmp(argv[1], "-a") == 0) Opt.Show_Hidden_File = 1; if (strcmp(argv[1], "-d") == 0) Opt.Show_File = 0; } else strcpy(Path, argv[1]); } if (argc == 3) { if (strcmp(argv[1], "-a") == 0) Opt.Show_Hidden_File = 1; if (strcmp(argv[1], "-d") == 0) Opt.Show_File = 0; strcpy(Path, argv[2]); } int Dir_Num = 0, File_Num = 0; puts(Path); Tree_Maker(Path, 1, Opt, &Dir_Num, &File_Num); printf("\n%d directories, %d files\n", Dir_Num, File_Num); //printf("Reg: %d Chr: %d Blk: %d Sock: %d Fifo: %d\n", Reg, Chr, Blk, Sock, Fifo); return 0; }