Interesting applet-count the number of different types of files in the system

Source: Internet
Author: User
Tags lstat

In linux, there are 7 types of files: common files, directories, link files, character device files, block device files, socket files, and fifo files. In general, we should be able to guess the most common and directory files, but what is the specific data?

I. Key Points of knowledge

Two things are required to achieve this purpose:

1) Identify the file type

The information of a file is encapsulated into a struct:

          struct stat {              dev_t     st_dev;     /* ID of device containing file */              ino_t     st_ino;     /* inode number */              mode_t    st_mode;    /* protection */              nlink_t   st_nlink;   /* number of hard links */              uid_t     st_uid;     /* user ID of owner */              gid_t     st_gid;     /* group ID of owner */              dev_t     st_rdev;    /* device ID (if special file) */              off_t     st_size;    /* total size, in bytes */              blksize_t st_blksize; /* blocksize for filesystem I/O */              blkcnt_t  st_blocks;  /* number of blocks allocated */              time_t    st_atime;   /* time of last access */              time_t    st_mtime;   /* time of last modification */              time_t    st_ctime;   /* time of last status change */          };

The st_mode member records the file type. You can use macros such as S_ISREG (mode) to identify the type.
The following functions are required to obtain the File status information:

       int stat(const char *path, struct stat *buf);       int fstat(int filedes, struct stat *buf);       int lstat(const char *path, struct stat *buf);

The differences between lstat () and stat () are mainly for linked files. stat () returns the information of the files to which the linked files point, while lstat () is for the linked files themselves.

2). traverse the directory

When directory traversal is performed, there is another struct to return the node file obtained through traversal.

          struct dirent {              ino_t          d_ino;       /* inode number */              off_t          d_off;       /* offset to the next dirent */              unsigned short d_reclen;    /* length of this record */              unsigned char  d_type;      /* type of file */              char           d_name[256]; /* filename */          };

The d_name member contains the name information of the current node item, And the d_type member contains the file type information of the current node item. (In fact, this type of information is enough for the statistics file type. You do not need to use the file information mentioned above to read the function)
The following functions are required to traverse a directory:

struct dirent *readdir(DIR *dir);DIR *opendir(const char *name);int closedir(DIR *dir);int chdir(const char *path);int fchdir(int fd);
Ii. Example

The complete procedure is as follows:

//this program is work for produce count of the type of files.//i.e: normal file, directory, symbolic file, device file and so on.#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <dirent.h>//type of filestypedef enum FileType {TYPE_LNK,TYPE_REG,TYPE_DIR,TYPE_CHR,TYPE_BLK,TYPE_FIFO,TYPE_SOC,TYPE_ERR,TYPE_CNT,}FILETYPE;static unsigned long count[TYPE_CNT];//count of the type of filestatic int recur = 0;//the depth of recursionstatic int recur_max;//tha max value of recursion depthtypedef  int ( * FUNC) ( char *pathname);static int inline recalRecurMax( int recur, int *recur_max){return *recur_max = *recur_max<recur?recur:*recur_max;}//identify the type of a filestatic int file_type( char *pathname){intret;struct statbuf;ret = lstat( pathname, &buf);//could't use stat(), because of the link file .if( ret<0){perror(" ");return TYPE_ERR;}FILETYPE type;switch( (buf.st_mode&S_IFMT) ){case S_IFLNK:type  = TYPE_LNK;break;case S_IFREG:type = TYPE_REG;break;case S_IFDIR:type = TYPE_DIR;break;case S_IFCHR:type = TYPE_CHR;break;case S_IFBLK:type = TYPE_BLK;break;case S_IFIFO:type = TYPE_FIFO;break;case S_IFSOCK:type = TYPE_SOC;break;default :type = TYPE_ERR;}return type;//return the type of this file}static  int ftw( char *rootpath, FUNC callback){recur++;recalRecurMax( recur, &recur_max);//record the max value of recursion depthDIR*pdir;pdir = opendir( rootpath);//open this directoryif( NULL==pdir ){perror(" ");return 0;}int ret;ret = chdir( rootpath);//enter this directoryif( ret<0){perror(" ");return 0;}struct dirent*pdirent;do{pdirent = readdir( pdir);//be carefull, this function will traverse all files in this directory.if( NULL!=pdirent){int type;type = callback( pdirent->d_name );//count the type of file//printf("%s, %d\n", pdirent->d_name, type);count[type]++;if( (DT_DIR==pdirent->d_type)//enter sub-directory&&(strcmp( pdirent->d_name, ".") )!=0&&(strcmp( pdirent->d_name, ".."))!=0 ){int ret;ret = ftw( pdirent->d_name, callback);if( !ret)printf("error: %s is not a valid path\n", pdirent->d_name);}}}while( NULL!=pdirent );chdir("..");closedir( pdir);recur --;return 1;}static void show( unsigned long count[]){double sum=0;inti;for( i=0; i< TYPE_CNT; i++){sum+= count[i];}printf( "LNK: %ld --%%%f\n", count[TYPE_LNK], count[TYPE_LNK]*100/sum);printf( "REG: %ld --%%%f\n", count[TYPE_REG], count[TYPE_REG]*100/sum);printf( "DIR: %ld --%%%f\n", count[TYPE_DIR], count[TYPE_DIR]*100/sum);printf( "CHR: %ld --%%%f\n", count[TYPE_CHR], count[TYPE_CHR]*100/sum);printf( "BLK: %ld --%%%f\n", count[TYPE_BLK], count[TYPE_BLK]*100/sum);printf( "FIFO: %ld --%%%f\n", count[TYPE_FIFO], count[TYPE_FIFO]*100/sum);printf( "SOC: %ld --%%%f\n", count[TYPE_SOC], count[TYPE_SOC]*100/sum);printf( "ERR: %ld --%%%f\n", count[TYPE_ERR], count[TYPE_ERR]*100/sum);printf(" recur_max = %d\n", recur_max);}int main( int argc, char *argv[]){if( 2!=argc ){printf("usage: a.out  <pathname>\n");return 0;}intret;ret = ftw( argv[1], file_type);show( count);if( !ret)printf(" %s is not a valid path\n", argv[1]);return 0;}

Of course, there are actually many simple ways to complete this function, such as ftw () and other functions.

After running the above program in your system, the result is as follows:

[root@localhost ftw]# ./interesting.out /LNK     : 19448 --%4.339260REG     : 330217 --%73.678398DIR     : 98236 --%21.918530CHR     : 152 --%0.033914BLK     : 47 --%0.010487FIFO    : 4 --%0.000892SOC     : 83 --%0.018519ERR     : 0 --%0.000000 recur_max = 14

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.