//!
//! 随笔:Linux下获取文件与目录
//!
//! == 随笔介绍 ==
//! 提供一个用于在Linux下获取文件名和目录的类,有两种方式,
//! 一种是将文件与目录分别归类到容器中,另一种是将文件与目录放入同一个容器,
//! 但带有描述结构的信息
//! == 随笔介绍 ==
//!
//!
//! == 内容展示 ==
//! 1.main()中的使用测试
//! 2.scan_files.h头文件代码
//! 3.测试结果显示
//! == 内容展示 ==
//!
//!
#include "scan_files.h"
#include <iostream>
using namespace std;
void test_1()
{
cout<<endl<<"== test_1 =="<<endl;
string path = "/home/red/open/save_test/test_dir/";
vector<string> vec_dir;
vector<string> vec_files;
bool ok = scan_files::get_files(path,vec_files,vec_dir);
if(ok)
{
cout<<"== 所有目录 =="<<endl;
for(auto a:vec_dir)
{
cout<<a<<endl;
}
cout<<"== 所有文件 =="<<endl;
for(auto a:vec_files)
{
cout<<a<<endl;
}
cout<<"目录数: "<<vec_dir.size()<<" | 文件数: "<<vec_files.size()<<endl;
}
}
void test_2()
{
cout<<endl<<"== test_2 =="<<endl;
string path = "/home/red/open/save_test/test_dir";
vector<scan_files::tree> vec_tree;
bool ok = scan_files::get_tree_dir(path,vec_tree);
if(ok)
{
for(auto a:vec_tree)
{
cout<<a.deep<<"|"<<a.type<<"|"<<a.name<<endl;
cout<<a.path_abs<<endl;
}
cout<<"目录与文件数(加根节点): "<<vec_tree.size()<<endl;
}
}
int main()
{
cout<<"===== begin ====="<<endl;
test_1();
test_2();
cout<<"===== end ====="<<endl;
return 0;
}
//!
//! scan_files.h
//!
#ifndef SCAN_FILES_H
#define SCAN_FILES_H
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string>
#include <vector>
using namespace std;
//!
//! 功能:获取目录下文件和目录
//! 注意:Linux系统
//!
class scan_files
{
public:
//带层级的树形结构
struct tree
{
int deep; //目录递归深度
string type; //目录类型(REG/DIR)
string name; //文件或者目录名称
string path_abs; //绝对路径
};
public:
//递归的将路径下所有普通文件和目录放入容器
//参数1:扫描目录(绝对路径)
//参数2:存储文件的容器
//参数3:存储目录的容器
//返回值:成功或者失败
static bool get_files(const string &path,vector<string> &vec_files,vector<string> &vec_dir)
{
DIR *pdir_all = opendir(path.c_str());
if(pdir_all == nullptr) return false;
dirent *info_dir;
vector<string> vec_save_dir;
struct stat ct_stat;
while ((info_dir = readdir(pdir_all)) != nullptr)
{
//获取绝对路径后判断文件类型
string st_path = path +"/"+ info_dir->d_name;
stat(st_path.c_str(),&ct_stat);
//将绝对路径添加到容器后返回
if(S_ISDIR(ct_stat.st_mode) == true
&& (strcmp(info_dir->d_name,".") != 0)
&& (strcmp(info_dir->d_name,"..") != 0))
{
string in_path = path +"/"+ info_dir->d_name;
vec_save_dir.push_back(in_path);
}
else if(S_ISREG(ct_stat.st_mode))
{
string in_files = path +"/"+ info_dir->d_name;
vec_files.push_back(in_files);
}
}
vec_dir.insert(vec_dir.end(),vec_save_dir.begin(),vec_save_dir.end());
//递归搜索
for(size_t i=0;i<vec_save_dir.size();i++)
{ get_files(vec_save_dir[i],vec_files,vec_dir); }
closedir(pdir_all);
return true;
}
//get_tree()的简单调用
//参数1:扫描目录(绝对路径)
//参数2:文件与目录结构容器
static bool get_tree_dir(const string &path_abs,vector<tree> &vec_tree)
{ return get_tree(path_abs,".",vec_tree,0); }
//递归获取带层级的文件目录,深度优先(获取当前层文件,然后进入子文件夹获取所有内容,再获取第二个子文件夹)
//参数1:扫描目录(绝对路径)
//参数2:文件或目录名称
//参数3:文件与目录结构容器
//参数4:递归深度
static bool get_tree(const string &abs,const string &rel,vector<tree> &vec_tree,int deep)
{
DIR *pdir_all = opendir(abs.c_str());
if(pdir_all == nullptr) return false;
tree tm;
tm.deep = deep;
tm.type = "DIR";
tm.path_abs = abs;
tm.name = rel;
vec_tree.push_back(tm);
deep++;
dirent *info_dir;
vector<string> vec_save_dir;
struct stat ct_stat;
while ((info_dir = readdir(pdir_all)) != nullptr)
{
//获取绝对路径后判断文件类型
string st_path = abs +"/"+ info_dir->d_name;
stat(st_path.c_str(),&ct_stat);
//将绝对路径添加到容器后返回
if(S_ISDIR(ct_stat.st_mode) == true
&& (strcmp(info_dir->d_name,".") != 0)
&& (strcmp(info_dir->d_name,"..") != 0))
{ vec_save_dir.push_back(info_dir->d_name); }
else if(S_ISREG(ct_stat.st_mode))
{
tree tm;
tm.deep = deep;
tm.type = "REG";
tm.path_abs = abs +"/"+ info_dir->d_name;
tm.name = info_dir->d_name;
vec_tree.push_back(tm);
}
}
//递归搜索
for(size_t i=0;i<vec_save_dir.size();i++)
{ get_tree(abs+"/"+vec_save_dir[i],vec_save_dir[i],vec_tree,deep); }
closedir(pdir_all);
return true;
}
//判断目录
static bool is_dir(string path)
{
struct stat ct_stat;
stat(path.c_str(),&ct_stat);
return S_ISDIR(ct_stat.st_mode);
}
//判断普通文件
static bool is_file(string path)
{
struct stat ct_stat;
stat(path.c_str(),&ct_stat);
return S_ISREG(ct_stat.st_mode);
}
};
#endif // SCAN_FILES_H
/*
* 测试结果展示如下:
* 1.ree命令的数结构
* 2.test_1的输出
* 2.test_2的输出
*/
/*
* tree 的树结构
*
.
├── t1
│ ├── word1.txt
│ ├── word2.txt
│ └── word3.txt
├── t2
│ ├── class1.mp4
│ ├── class2.mp4
│ ├── class3.mp4
│ ├── pic
│ │ ├── newpic
│ │ │ ├── jk.jpeg
│ │ │ ├── mv.jpeg
│ │ │ └── open.jpeg
│ │ ├── p1.jpg
│ │ ├── p2.jpg
│ │ └── p3.jpg
│ ├── pic1.png
│ ├── pic2.png
│ └── word
└── t3
├── d1
│ ├── h1.txt
│ └── h2.txt
├── d2
│ ├── r1.txt
│ └── r2.txt
└── d3
├── p1.txt
└── p2.txt
9 directories, 20 files
*/
/*
* test_1
*
== test_1 ==
== 所有目录 ==
/home/red/open/save_test/test_dir/t1
/home/red/open/save_test/test_dir/t2
/home/red/open/save_test/test_dir/t3
/home/red/open/save_test/test_dir/t2/word
/home/red/open/save_test/test_dir/t2/pic
/home/red/open/save_test/test_dir/t2/pic/newpic
/home/red/open/save_test/test_dir/t3/d3
/home/red/open/save_test/test_dir/t3/d1
/home/red/open/save_test/test_dir/t3/d2
== 所有文件 ==
/home/red/open/save_test/test_dir/t1/word3.txt
/home/red/open/save_test/test_dir/t1/word1.txt
/home/red/open/save_test/test_dir/t1/word2.txt
/home/red/open/save_test/test_dir/t2/pic1.png
/home/red/open/save_test/test_dir/t2/class1.mp4
/home/red/open/save_test/test_dir/t2/class2.mp4
/home/red/open/save_test/test_dir/t2/class3.mp4
/home/red/open/save_test/test_dir/t2/pic2.png
/home/red/open/save_test/test_dir/t2/pic/p1.jpg
/home/red/open/save_test/test_dir/t2/pic/p2.jpg
/home/red/open/save_test/test_dir/t2/pic/p3.jpg
/home/red/open/save_test/test_dir/t2/pic/newpic/jk.jpeg
/home/red/open/save_test/test_dir/t2/pic/newpic/mv.jpeg
/home/red/open/save_test/test_dir/t2/pic/newpic/open.jpeg
/home/red/open/save_test/test_dir/t3/d3/p1.txt
/home/red/open/save_test/test_dir/t3/d3/p2.txt
/home/red/open/save_test/test_dir/t3/d1/h1.txt
/home/red/open/save_test/test_dir/t3/d1/h2.txt
/home/red/open/save_test/test_dir/t3/d2/r2.txt
/home/red/open/save_test/test_dir/t3/d2/r1.txt
目录数: 9 | 文件数: 20
*/
/*
* test_2
*
== test_2 ==
0|DIR|.
/home/red/open/save_test/test_dir
1|DIR|t1
/home/red/open/save_test/test_dir/t1
2|REG|word3.txt
/home/red/open/save_test/test_dir/t1/word3.txt
2|REG|word1.txt
/home/red/open/save_test/test_dir/t1/word1.txt
2|REG|word2.txt
/home/red/open/save_test/test_dir/t1/word2.txt
1|DIR|t2
/home/red/open/save_test/test_dir/t2
2|REG|pic1.png
/home/red/open/save_test/test_dir/t2/pic1.png
2|REG|class1.mp4
/home/red/open/save_test/test_dir/t2/class1.mp4
2|REG|class2.mp4
/home/red/open/save_test/test_dir/t2/class2.mp4
2|REG|class3.mp4
/home/red/open/save_test/test_dir/t2/class3.mp4
2|REG|pic2.png
/home/red/open/save_test/test_dir/t2/pic2.png
2|DIR|word
/home/red/open/save_test/test_dir/t2/word
2|DIR|pic
/home/red/open/save_test/test_dir/t2/pic
3|REG|p1.jpg
/home/red/open/save_test/test_dir/t2/pic/p1.jpg
3|REG|p2.jpg
/home/red/open/save_test/test_dir/t2/pic/p2.jpg
3|REG|p3.jpg
/home/red/open/save_test/test_dir/t2/pic/p3.jpg
3|DIR|newpic
/home/red/open/save_test/test_dir/t2/pic/newpic
4|REG|jk.jpeg
/home/red/open/save_test/test_dir/t2/pic/newpic/jk.jpeg
4|REG|mv.jpeg
/home/red/open/save_test/test_dir/t2/pic/newpic/mv.jpeg
4|REG|open.jpeg
/home/red/open/save_test/test_dir/t2/pic/newpic/open.jpeg
1|DIR|t3
/home/red/open/save_test/test_dir/t3
2|DIR|d3
/home/red/open/save_test/test_dir/t3/d3
3|REG|p1.txt
/home/red/open/save_test/test_dir/t3/d3/p1.txt
3|REG|p2.txt
/home/red/open/save_test/test_dir/t3/d3/p2.txt
2|DIR|d1
/home/red/open/save_test/test_dir/t3/d1
3|REG|h1.txt
/home/red/open/save_test/test_dir/t3/d1/h1.txt
3|REG|h2.txt
/home/red/open/save_test/test_dir/t3/d1/h2.txt
2|DIR|d2
/home/red/open/save_test/test_dir/t3/d2
3|REG|r2.txt
/home/red/open/save_test/test_dir/t3/d2/r2.txt
3|REG|r1.txt
/home/red/open/save_test/test_dir/t3/d2/r1.txt
目录与文件数(加根节点): 30
*/