Linux下文件夹相关操作

程序中,经常会用到遍历文件夹、读取文件夹和读取文件目录等操作,本文就介绍Linux下操作文件目录的方法。
需求:遍历路径/home/workspace/test下所有的文件(文件夹、文件),输出其名字及大小。
代码:

#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<string>
#include<iostream>
using namespace std;
int main()
{
    DIR *pDir;  //定义目录流对象
    struct dirent *pDirent;  //目录文件结构
    struct stat info;  //文件状态信息结构
    string str = "/home/dingyan/test";
    if((pDir = opendir(str.c_str())) == NULL)  //打开目录文件流对象
    {
        cout<<"opendir failed!"<<endl;
    }
    while((pDirent = readdir(pDir)) != NULL)  //读取目录文件流对象
    {
        string strpath = str + "/" + pDirent->d_name;
        stat(strpath.c_str(),&info);  //取得文件对象的属性信息
        cout<<strpath<<":"<<info.st_size<<endl;;
    }
    return 0;
}

strpath路径下的文件列表:
这里写图片描述

程序执行输出:

/home/dingyan/test/..:4096
/home/dingyan/test/file1:0
/home/dingyan/test/.:4096
/home/dingyan/test/file3:809
/home/dingyan/test/file2:404

针对上述实例程序代码,我们先看一下结构体DIR,以下是DIR的定义:


    struct __dirstream
       {
        void *__fd;
        char *__data;
        int __entry_data;
        char *__ptr;
        int __entry_ptr;
        size_t __allocation;
        size_t __size;
        __libc_lock_define (, __lock)
       };
    typedef struct __dirstream DIR;

可以看出DIR是一个类似于File的内部结构,它可以通过以下函数返回:

    DIR *opendir(const char *pathname)

以下是一些利用该结构保存被读取的目录的信息:

    struct dirent *readdir(DIR *dp);
    void rewinddir(DIR *dp);
    int closedir(DIR *dp);
    long telldir(DIR *dp);
    void seekdir(DIR *dp,long loc);

细心的读者会发现程序输出中包含了文件.(点)和..(点点),即当前目录和上级目录文件。那么如何区分目录文件和正常文件之间呢,那就需要对结构pdirent进行分析了,目录文件它包含了其他文件的名字以及指向与这些文件有关的信息的指针。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件。已知结构pdirent的定义为:

struct dirent {
    ino_t   d_ino;  /* inode number */
    off_t   d_off;  /* offset to the next dirent */
    unsigned    short d_reclen; /* length of this record */
    unsigned char   d_type; /* type of file; not supported
                            by all file system types */
    char    d_name[256];    /* filename */
};

但是,该结构还是比较简单的,仅仅表示了目录文件下的文件的基本信息,还必须通过函数int stat(const char *file_name, struct stat *buf);根据d_name获取文件的详细信息,stat的结构定义如下:

struct stat {
            mode_t     st_mode;       //文件访问权限
            ino_t      st_ino;       //索引节点号
            dev_t      st_dev;        //文件使用的设备号
            dev_t      st_rdev;       //设备文件的设备号
            nlink_t    st_nlink;      //文件的硬连接数
            uid_t      st_uid;        //所有者用户识别号
            gid_t      st_gid;        //组识别号
            off_t      st_size;       //以字节为单位的文件容量
            time_t     st_atime;      //最后一次访问该文件的时间
            time_t     st_mtime;      //最后一次修改该文件的时间
            time_t     st_ctime;      //最后一次改变该文件状态的时间
            blksize_t st_blksize;    //包含该文件的磁盘块的大小
            blkcnt_t   st_blocks;     //该文件所占的磁盘块
          };

在结构dirent中d_type表示文件类型:

DT_BLK      This is a block device.
DT_CHR      This is a character device.
DT_DIR      This is a directory.
DT_FIFO     This is a named pipe (FIFO).
DT_LNK      This is a symbolic link.
DT_REG      This is a regular file.
DT_SOCK     This is a Unix domain socket.
DT_UNKNOWN  The file type is unknown.

至此,我们就发现通过d_type这一成员就可以对文件类型进行区分了,那么修改后的源码为:

#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<string>
#include<iostream>
using namespace std;
int main()
{
    DIR *pDir;
    struct dirent *pDirent;
    struct stat info;
    string str = "/home/dingyan/test";
    if((pDir = opendir(str.c_str())) == NULL)
    {
        cout<<"opendir failed!"<<endl;
    }
    while((pDirent = readdir(pDir)) != NULL)
    {
        if(pDirent->d_type == DT_REG)  //增加了类型判断
        {
            string strpath = str + "/" + pDirent->d_name;
            stat(strpath.c_str(),&info);
            cout<<strpath<<":"<<info.st_size<<endl;
        }
    }
    return 0;
}

输出结果为:

/home/dingyan/test/file1:0
/home/dingyan/test/file3:809
/home/dingyan/test/file2:404

这就是我们需要的啦。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值