C语言中的多级目录操作

该文详细介绍了在Linux环境下如何使用C语言进行文件系统操作,包括使用dirent.h和sys/stat.h等头文件处理目录结构,structdirent和structstat结构体的使用,以及创建多级目录、遍历目录、获取文件信息、计算目录大小和删除空目录的函数实现。
摘要由CSDN通过智能技术生成

一、用到的头文件和结构体解释

1.头文件

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

2.struct dirent 结构体

//原型
struct dirent
{
   long d_ino; 					/* inode number 索引节点号 */
   off_t d_off; 				/* offset to this dirent 在目录文件中的偏移 */
   unsigned short d_reclen; 	/* length of this d_name 文件名长 */
   unsigned char d_type; 		/* the type of d_name 文件类型 */
   char d_name [256]; 			/* file name (null-terminated) 文件名 */
}

//使用方式
struct dirent *dirp;
DIR *dp = opendir(const cahr *name);//打开目录
dirp = readdir(dp);//获取dp目录流的下个节点

3.struct stat结构体

//原型
struct stat  
{   
    dev_t       st_dev;     /* ID of device containing file -文件所在设备的ID*/  
    ino_t       st_ino;     /* inode number -inode节点号*/    
    mode_t      st_mode;    /* protection -文件类型*/    
    nlink_t     st_nlink;   /* number of hard links -链向此文件的连接数(硬连接)*/    
    uid_t       st_uid;     /* user ID of owner -user id*/    
    gid_t       st_gid;     /* group ID of owner - group id*/    
    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 - 创建时间*/    
};  
//使用方式
//原型int stat(const char *pathname, struct stat *statbuf);
struct stat info
stat(filePath, &info);// 获取文件信息
/*其中比较常用的就是获取文件类型 mode_t st_mode
info.st_mode 下面是长用到的宏函数:
S_ISLNK(st_mode)是否是一个连接
S_ISREG(st_mode)是否是一个常规文件
S_ISDIR(st_mode)是否是一个目录
S_ISCHR(st_mode)是否是一个字符设备
S_ISBLK(st_mode)是否是一个块设备
S_ISFIFO(st_mode)是否是一个FIFO文件
S_ISSOCK(st_mode)是否是一个SOCKET文件.*/
if (S_ISDIR(info.st_mode))//是否为目录判断

二、创建多级目录

void create_multistage_dir(char *dir)
{
	int i, len;
	char str[1024] = {0};
	strcpy(str, dir);
	len = strlen(str);
	for (i = 0; i < len; i++)
	{
		if (str[i] == '/')
		{
			str[i] = '\0';
			if (access(str, F_OK) != 0)
				mkdir(str, 0777);
			str[i] = '/';
		}
	}
	if (len > 0 && access(str, F_OK) != 0) // 检测是否创建成功
		mkdir(str, 0777);

	return;
}

三、获取指定目录的信息


void traverseDirectory(const char* path) {
    DIR* dir;
    struct dirent* entry;
    struct stat info;
    
    // 打开目录
    dir = opendir(path);
    
    if (dir == NULL) {
        printf("oprn dir failed >> %s\n", path);
        return;
    }
    
    // 遍历目录中的文件和子目录
    while ((entry = readdir(dir)) != NULL) {
        char filePath[256];
        snprintf(filePath, sizeof(filePath), "%s/%s", path, entry->d_name);
        
        // 获取文件信息
        stat(filePath, &info);
        
        if (S_ISDIR(info.st_mode)) {
            // 如果是目录,则递归遍历子目录
            if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                traverseDirectory(filePath);
            }
        } else {
            // 如果是文件,则打印文件名和文件路径
            printf("file name: %s\n", entry->d_name);
            printf("file path: %s\n", filePath);
        }
    }
    
    // 关闭目录
    closedir(dir);
}

四、计算指定目录大小

//计算的大小包含自身大小4096Byte
float getDirectorySize(const char *dir)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
    long long int totalSize = 0;

    if ((dp = opendir(dir)) == NULL)
    {
        fprintf(stderr, "Cannot open dir: %s\n", dir);
        return -1; // 可能是个文件,或者目录不存在
    }

    // 先加上自身目录的大小
    lstat(dir, &statbuf);
    totalSize += statbuf.st_size;

    while ((entry = readdir(dp)) != NULL)
    {
        char subdir[256];
        sprintf(subdir, "%s/%s", dir, entry->d_name);
        lstat(subdir, &statbuf);

        if (S_ISDIR(statbuf.st_mode))
        {
            if (strcmp(".", entry->d_name) == 0 ||
                strcmp("..", entry->d_name) == 0)
            {
                continue;
            }

            long long int subDirSize = GetDirectorySize(subdir);
            totalSize += subDirSize;
        }
        else
        {
            totalSize += statbuf.st_size;
        }
    }

    closedir(dp);
    return totalSize;
}

五、删除指定目录下的空目录

int remove_empty_directories(const char *path)
{
	DIR *dir = opendir(path);
	size_t path_len = strlen(path);
	int result = 0;

	if (dir)
	{
		struct dirent *entry;
		result = 0;

		while ((entry = readdir(dir)) != NULL)
		{
			char *file_name = entry->d_name;
			char *full_path = (char *)malloc(path_len + strlen(file_name) + 2);

			if (full_path)
			{
				struct stat statbuf;
				snprintf(full_path, path_len + strlen(file_name) + 2, "%s/%s", path, file_name);

				if (strcmp(file_name, ".") == 0 || strcmp(file_name, "..") == 0)
				{
					// 忽略当前目录和上级目录
					free(full_path);
					continue;
				}

				if (lstat(full_path, &statbuf) == 0)
				{
					if (S_ISDIR(statbuf.st_mode))
					{
						// 递归删除空目录
						if (remove_empty_directories(full_path) == 0)
						{
							// 删除空目录
							if (rmdir(full_path) == -1)
							{
								result = -1;
							}
						}
						else
						{
							result = -1;
						}
					}
				}
				free(full_path);
			}
		}

		closedir(dir);
	}

	return result;
}

六、特定格式的文件路径解析

int main() {
    char path[] = "/path0/path0/path0/file.txt";
    char *token;

    token = strtok(path, "/");
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok(NULL, "/");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值