随笔:Linux下获取文件与目录

//!
//! 随笔: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
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值