热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

有趣的小程序--统计系统中不同种类文件数量

在linux系统中有7中类型的文件:普通文件,目录,链接文件,字符设备文件,块设备文件,套接字文件,fifo文件。一般来说应该能猜到是普通文件和目录文件最多,但具体的数据又是多少?一.

        在linux系统中有7中类型的文件:普通文件,目录,链接文件,字符设备文件,块设备文件,套接字文件,fifo文件。一般来说应该能猜到是普通文件和目录文件最多,但具体的数据又是多少?

一.知识要点

                为了实现这个目的需要如下两个东西:

        1).辨别文件类型

               一个文件的信息会被封装成一个结构体:

          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 */
};

               其中st_mode成员中记载了文件类型。可以用 S_ISREG(mode)等宏去鉴别类型。
                希望获得文件的状态信息又需要用到如下函数

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

               其中的 lstat()和 stat()的不同主要是针对链接文件,stat()会返回链接文件指向的文件信息,而lstat()则是链接文件本身。


       2).遍历目录

        对目录进行遍历的时候,为了返回遍历得到的节点文件,还有另一种结构体

          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 */
};

         其中的d_name成员包含了本节点项的名字信息,d_type成员包含了本节点项的文件类型信息。(实际上就用这个类型信息就足够统计文件类型了,不用再使用上面涉及到的文件信息读取函数)
         遍历一个目录需要用到的函数如下

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

 

二.例子

       完整的程序如下

//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
#include
#include
#include
#include
#include

//type of files
typedef 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 file
static int recur = 0;//the depth of recursion
static int recur_max;//tha max value of recursion depth

typedef int ( * FUNC) ( char *pathname);


static int inline recalRecurMax( int recur, int *recur_max)
{

return *recur_max = *recur_max}

//identify the type of a file
static 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 depth

DIR*pdir;
pdir = opendir( rootpath);//open this directory
if( NULL==pdir )
{
perror(" ");
return 0;
}

int ret;
ret = chdir( rootpath);//enter this directory
if( 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{
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 \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;

}


        当然实际上有很多简洁的办法完成这个功能,比如ftw()等函数。

        将上面的程序在自己系统中运行后,获得的结果如下

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



 


推荐阅读
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 本文旨在探讨Swift中的Closure与Objective-C中的Block之间的区别与联系,通过定义、使用方式以及外部变量捕获等方面的比较,帮助开发者更好地理解这两种机制的特点及应用场景。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • 本文介绍了如何通过安装和配置php_uploadprogress扩展来实现文件上传时的进度条显示功能。通过一个简单的示例,详细解释了从安装扩展到编写具体代码的全过程。 ... [详细]
  • 本文详细探讨了 Android Service 组件中 onStartCommand 方法的四种不同返回值及其应用场景。Service 可以在后台执行长时间的操作,无需提供用户界面,支持通过启动和绑定两种方式创建。 ... [详细]
  • Java中提取字符串的最后一部分
    本文介绍了如何使用Java中的substring()和split()方法来提取字符串的最后一部分,特别是在处理包含特殊字符的路径时的方法与技巧。 ... [详细]
  • Gradle 是 Android Studio 中默认的构建工具,了解其基本配置对于开发效率的提升至关重要。本文将详细介绍如何在 Gradle 中定义和使用共享变量,以确保项目的一致性和可维护性。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • 【MySQL】frm文件解析
    官网说明:http:dev.mysql.comdocinternalsenfrm-file-format.htmlfrm是MySQL表结构定义文件,通常frm文件是不会损坏的,但是如果 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • 本文探讨了如何利用 Android 的 Movie 类来展示 GIF 动画,并详细介绍了调整 GIF 尺寸以适应不同布局的方法。同时,提供了相关的代码示例和注意事项。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 本文介绍了如何在 Django 项目中集成和配置 REST Framework,以支持 API 开发。通过在 settings.py 文件中注册 'rest_framework' 应用,可以轻松启用这一功能。 ... [详细]
  • PHP中Smarty模板引擎自定义函数详解
    本文详细介绍了如何在PHP的Smarty模板引擎中自定义函数,并通过具体示例演示了这些函数的使用方法和应用场景。适合PHP后端开发者学习。 ... [详细]
  • C/C++ 应用程序的安装与卸载解决方案
    本文介绍了如何使用Inno Setup来创建C/C++应用程序的安装程序,包括自动检测并安装所需的运行库,确保应用能够顺利安装和卸载。 ... [详细]
author-avatar
佳妤善真1729
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有