目录操作函数

头文件:include <unistd.h>

1、获取当前目录

在系统命令行下我们可以直接输入命令pwd 来获取当前的工作目录,但是你知道这个命令是怎么执行的吗?它是由系统通过 shell 程序来解释执行的,我们也可以自己编写程序调用getcwd函数获取当前的工作目录。

函数声明:

char * getcwd(char * buf,size_t size);

getcwd函数把当前目录的名字写到给定的缓冲区buf里。如果目录的名字超出了参数size给出的缓冲区长度(一个ERANGE错误),它就返回NULL。如果成功,它返回指针buf,我们可以访问buf来获取当前的目录。

例如:

char strpwd[301];
memset(strpwd,0,sizeof(strpwd))
getcwd(strpwd,300);
printf("当前目录是:%s\n",strpwd);

2、切换目录

函数声明:

int chdir(const char *path);

(1) 内核解析参数中的路径名,并确保这个路径名有效。为了做到这一点,就路径名解析而言,内核使用相同的算法。如果路径名无效,它输出错误消息并退出。

(2) 如果路径名有效,内核定位该目录的索引节点,并检查它的文件类型和权限位,确保目标文件是目录以及进程的所有者可以访问该目录(否则改变到新目录就没有用)。

(3) 内核用新目标目录的路径名和/或索引节点替换u区中当前目录路径名和/或它的索引节点号。

就像我们在shell里使用cd命令来切换目录一样,在程序里则可以使用chdir系统调用来实现目录的变更。

返回值:0-切换成功;非0-失败。

3、目录的创建和删除

在系统命令行下我们可以通过mkdir和rmdir命令通过shell来创建一个目录和删除一个目录,如果在程序中呢,总不可能由程序员自己去手动创建吧,一般都是程序自动创建一个目录来存放文件。

创建目录函数的声明:

int mkdir(const char *pathname, mode_t mode);

mode的含义将按open系统调用的O_CREAT选项中的有关定义设置,当然,它还要服从umask的设置况。是不是看不明白?那先固定填00755,注意,00不要省略哦。

例如:

mkdir("/tmp/aaa",00755); // 创建/tmp/aaa目录

删除目录函数的声明:

int rmdir(const char *pathname);

4、获取目录中的文件列表

获取目录中的文件列表,类似于ls命令。

在实际开发中,我们经常要处理文件,文件是存放在目录中的,在处理文件之前,必须先知道目录中有哪些文件,所以要获取目录中的文件列表。涉及到的库函数如下:

1、包含头文件

#include <dirent.h>

2、库函数

//打开目录的函数opendir的声明。

DIR *opendir(const char *pathname);

//读取目录的函数readdir的声明。

struct dirent *readdir(DIR *dirp);

//关闭目录的函数closedir的声明。

int closedir(DIR *dirp);

3、数据结构

DIR是目录指针,就像文件操作时的文件指针。

调用一次readdir,返回结构体struct dirent(在dirent.h中声明,程序员只管用就行了)的指针,存放本次读取到的文件的信息,就像文件操作时调用一次fgets一样,但是fgets调用获取的内容是一个字符串,readdir返回的是结构体。

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 [NAME_MAX+1];  // file name文件名,最长255字符
};

我们只需要关注结构体的d_type和d_name成员,其它的不必关心。

d_name文件名或目录名。

d_type描述了文件的类型,有多种取值,最重要的是8和4,8-常规文件(A regular file);4-目录(A directory),其它的暂时不关心。

 5、应用实例

创建导出日志文件

#define NVX_EXPORT_LOG_FILE_SUFFIX ".csv"
/**
 * @fn      FileExportNameCreate
 * @brief   创建导出文件名
 * @param[in]   path 导出路径
 * @param[out]  
 * @return
 * @retval  0.成功
 * @retval  other.失败
 */
int FileExportNameCreate(char *path, string &fileFullName)
{
    int ret   = -1;
    int index = 2;
    time_t t  = 0;
    struct tm nowTime;
    char tmpbuf[128] = {'\0'};
    string fileName;
    string fileNameTmp;

    /*
    **生成文件名称
    导出查询后勾选的日志信息
    日志导出文件命名规则:日志查询开始日期_时间_log_[重复文件号],例如:20181227_000000_log  
    */
    t = time(NULL);
    localtime_r(&t, &nowTime);
    strftime(tmpbuf, sizeof(tmpbuf), "%Y%m%d_%H%M%S", &nowTime);
    fileName = tmpbuf+(string)"_log"+(string)NVX_EXPORT_LOG_FILE_SUFFIX;
    fileNameTmp = tmpbuf+(string)"_log";

    struct dirent * pdirent;
    DIR  * pdir = opendir(path);
    if(NULL == pdir)
    {
        printf("opendir err:%s, path:%s\n", strerror(errno), path);
        goto EXIT;
    }

AGAIN:
    for(pdirent = readdir(pdir);pdirent != NULL;pdirent = readdir(pdir))
    {
        if(0 == strcmp(pdirent->d_name,fileName.c_str()))    //已经存在该文件
        {
            memset(tmpbuf, 0, sizeof(tmpbuf));
            snprintf(tmpbuf, sizeof(tmpbuf), "_%02d", index++);
            fileName = fileNameTmp + tmpbuf +(string)NVX_EXPORT_LOG_FILE_SUFFIX;
            seekdir(pdir, 0);
            goto AGAIN;
        }
    }
    
    closedir(pdir);
    ret = 0;

    fileFullName = (string)path +(string)"/"+ fileName;
    memset(tmpbuf, 0, sizeof(tmpbuf));
    snprintf(tmpbuf, sizeof(tmpbuf), "touch %s", fileFullName.c_str());
    system(tmpbuf);
EXIT:
    return ret;
}

递归获取目录下文件:

#include <iostream>
#include <string>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
extern "C"{
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    #include <dirent.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
}
using namespace std;

void getAllFiles(string path, vector<string>& files)
{
    DIR *dir;
    struct dirent *ptr;
    if((dir=opendir(path.c_str()))==NULL){
        perror("Open dri error...");
        exit(1);
    }
    while((ptr=readdir(dir))!=NULL){
        if(strcmp(ptr->d_name,".")==0||strcmp(ptr->d_name,"..")==0)
            continue;
        else if(ptr->d_type==8)//file
            files.push_back(path+"/"+ptr->d_name);
        else if(ptr->d_type==10)//link file
            continue;
        else if(ptr->d_type==4){
            //files.push_back(ptr->d_name);//dir
            getAllFiles(path+"/"+ptr->d_name,files);
        }
    }
    closedir(dir);
}
int main(int argc,char **argv){
    if(argc<2){
        cout<<"USAGE:./a.out path"<<endl;
        exit(-1);
    }
    char * filePath = argv[1];
    cout<< "filePath:" << filePath << endl;
    vector<string> files;
    //char * distAll = "allFiles.txt";
    getAllFiles(filePath, files);
    //ofstream ofn(distAll);
    int size = files.size();
    //ofn << size << endl;
    cout << "size:" << size << endl;
    for (int i = 0; i<size; i++)
    {
        //ofn << files[i] << endl;
        cout << files[i] << endl;
    }
    //ofn.close();
    return 0;
}

 递归删除目录文件

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

/**
 * @fn     isDirectoryEmpty
 * @brief  目录检查
 *             dirname:  目录名
 * @param[out]
 * @return
 * @retval    0 : 不是空目录
 * @retval    1 : 空目录
 */
int isDirectoryEmpty(char* dirname)
{
	int            n = 0;
	struct dirent* d = NULL;
	DIR*           dir = opendir(dirname);

	// Not a directory or doesn't exist
	if (dir == NULL)
	{
		return 1;
	}		

	while ((d = readdir(dir)) != NULL)
	{
		printf("dirname = %s, n = %d\n", d->d_name, n);
		if (++n > 2)
			break;
	}

	closedir(dir);
	if (n <= 2)  // Directory Empty
	{
		return 1;
	}	
	else
		return 0;
}
/**
 * @fn     delDir
 * @brief  目录删除
 *             path:  路径名
 * @param[out]
 * @return
 * @retval    0 : 目录不存在
 * @retval  非0 : 成功
 */
int delDir(char *path)
{
	DIR* dirp = opendir(path); //打开目录src,并拷贝到(DIR定义)目录dirp
	struct dirent* pde = NULL; //pde指向结构dirent(pde命名自定义)
	char old[301];
	int cnt = 0;
	struct stat st;

	if (dirp == NULL)
	{
		printf("dir = %s not exist.", path);
		goto EXIT;
	}

	getcwd(old, sizeof(old));
	chdir(path);

	while ((pde = readdir(dirp)) != NULL) //返回参数dp目录流的下个目录进入点
	{
		if (0 == stat(pde->d_name, &st)) //函数 stat,用来获取文件的属性
		{
			if (S_ISDIR(st.st_mode))
			{
				//说明是一个文件夹
				if (strcmp(pde->d_name, ".") != 0 && strcmp(pde->d_name, "..") != 0)
				{
					delDir(pde->d_name);
				}
			}
			else
			{
				//说明是一个普通文件
				unlink(pde->d_name);
				cnt++;
			}
		}
	}

	chdir(old);
	rmdir(path);
	closedir(dirp);

EXIT:
	return cnt;
}
int main(){
	int ret = -1;
	char path[] = "/home/huqin/bstr/Demo/test";
	
	ret = delDir(path);
	printf("del dir succeed filenum:%d\n",ret);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值