头文件: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;
}