Skip to content

目录操作

在Linux下对于目录其实也是一个文件。但是目录不能直接进行读写,因为目录中所存储的是目录项数据。

目录项

  • 记录了该目录下面的子目录和文件的信息(如文件名、文件大小等)。
  • 对目录进行操作,即读取目录项以获取该目录下的文件夹和文件。

打开目录:opendir

c
OPENDIR(3)    Linux Programmer's Manual    OPENDIR(3)  

NAME  
    opendir, fdopendir - open a directory  

SYNOPSIS  
    #include <sys/types.h>  
    #include <dirent.h>  

    DIR *opendir(const char *name);  
    /*  
    @描述:  
        打开一个指定的目录文件  
    @name:  
        需要打开的目录的名字(路径)  
    @return:  
        成功返回目录指针  
        失败返回NULL,同时errno被设置  
    */

操作目录:mkdir / readdir

创建目录
c
MKDIR(2)    Linux Programmer's Manual    MKDIR(2)  

NAME  
    mkdir, mkdirat - create a directory  

SYNOPSIS  
    #include <sys/stat.h>  
    #include <sys/types.h>  

    int mkdir(const char *pathname, mode_t mode);  
    /*  
    @描述:  
        创建一个目录  
    @pathname:  
        需要创建的目录的名字(带路径)  
    @mode:  
        权限  
    @return:  
        成功返回0  
        失败返回-1,同时errno被设置  
    */
读取目录内容
c
READDIR(3)    Linux Programmer's Manual    READDIR(3)  

NAME  
    readdir - read a directory  

SYNOPSIS  
    #include <dirent.h>  
    struct dirent *readdir(DIR *dirp);  
    /*  
    @描述:  
        在打开的目录文件中,读取目录文件的内容  
    @dirp:  
        目录文件的目录指针  
    @return:  
        成功返回目录文件中的一个子目录/文件的结构体指针  
        失败/读取完毕返回NULL  
    */  

// 目录项结构体  
struct dirent {  
    ino_t    d_ino;       /* Inode number */  
    off_t    d_off;       /* Not an offset; see below */  
    unsigned short d_reclen; /* Length of this record */  
    unsigned char d_type;    /* Type of file; not supported by all filesystem types */  
    char     d_name[256];  /* Null-terminated filename */  
};

注意

  1. 每次读取目录都会往后自动偏移。
  2. 结构体成员变量中,仅d_inod_name是Linux系统普遍支持的(为保持可移植性,建议只用这两个成员)。

关闭目录:closedir

c
CLOSEDIR(3)    Linux Programmer's Manual    CLOSEDIR(3)  

NAME  
    closedir - close a directory  

SYNOPSIS  
    #include <sys/types.h>  
    #include <dirent.h>  

    int closedir(DIR *dirp);  
    /*  
    @描述:  
        关闭一个打开了的目录  
    @dirp:  
        需要关闭的目录指针  
    @return:  
        成功返回0  
        失败返回-1,同时errno被设置  
    */

偏移目录项

设置目录项偏移位置
c
SEEKDIR(3)    Linux Programmer's Manual    SEEKDIR(3)  

NAME  
    seekdir - set the position of the next readdir() call in the directory stream.  

SYNOPSIS  
    #include <dirent.h>  
    void seekdir(DIR *dirp, long loc);  
    /*  
    @描述:  
        设置目录项下一次读取位置  
    @dirp:  
        需要修改下一次读取位置的目录指针  
    @loc:  
        修改位置值  
    */
获取目录项偏移量
c
TELLDIR(3)    Linux Programmer's Manual    TELLDIR(3)  

NAME  
    telldir - return current location in directory stream  

SYNOPSIS  
    #include <dirent.h>  
    long telldir(DIR *dirp);  
    /*  
    @描述:  
        获取当前目录项的偏移量  
    @dirp:  
        需要获取偏移量的目录指针  
    @return:  
        返回当前偏移量  
    */

文件属性的获取

c
STAT(2)    Linux Programmer's Manual    STAT(2)  

NAME  
    stat, fstat, lstat, fstatat - get file status  

SYNOPSIS  
    #include <sys/types.h>  
    #include <sys/stat.h>  
    #include <unistd.h>  

    int stat(const char *pathname, struct stat *statbuf);  
    /*  
    @描述:  
        获取pathname指定的文件的属性信息  
    @pathname:  
        文件名字(包含路径)  
    @statbuf:  
        指向存储文件属性信息的结构体空间  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */  

    int fstat(int fd, struct stat *statbuf);  
    /*  
    @fd:  
        文件描述符  
    @statbuf:  
        指向struct stat结构体  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */  

    int lstat(const char *pathname, struct stat *statbuf);  
    /*  
    @pathname:  
        文件名字(包含路径)  
    @statbuf:  
        指向struct stat结构体  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */  

struct stat {  
    dev_t     st_dev;      /* ID of device containing file */  
    ino_t     st_ino;      /* Inode number */  
    mode_t    st_mode;     /* File type and mode */  
    nlink_t   st_nlink;    /* Number of hard links */  
    uid_t     st_uid;      /* User ID of owner */  
    gid_t     st_gid;      /* Group ID of owner */  
    dev_t     st_rdev;     /* Device ID (if special file) */  
    off_t     st_size;     /* Total size, in bytes */  
    blksize_t st_blksize;  /* Block size for filesystem I/O */  
    blkcnt_t  st_blocks;   /* Number of 512B blocks allocated */  
    struct timespec st_atim;  /* Time of last access */  
    struct timespec st_mtim;  /* Time of last modification */  
    struct timespec st_ctim;  /* Time of last status change */  
};  

// st_mode解析示例:  
switch(st.st_mode & S_IFMT) {  
    case S_IFDIR:  // 目录文件  
    case S_IFCHR:  // 字符设备  
    case S_IFREG:  // 普通文件  
    // ...  
}  

// 权限判断示例:  
if (st.st_mode & S_IRUSR) { /* 所属用户有可读权限 */ }

删除文件/目录

删除文件

c
UNLINK(2)    Linux Programmer's Manual    UNLINK(2)  

NAME  
    unlink, unlinkat - delete a name and possibly the file it refers to  

SYNOPSIS  
    #include <unistd.h>  
    int unlink(const char *pathname);  
    /*  
    @描述:  
        删除一个文件(删除文件的inode)  
    @pathname:  
        文件名(可含路径)  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */

删除目录

c
RMDIR(2)    Linux Programmer's Manual    RMDIR(2)  

NAME  
    rmdir - delete a directory  

SYNOPSIS  
    #include <unistd.h>  
    int rmdir(const char *pathname);  
    /*  
    @描述:  
        删除一个空目录  
    @pathname:  
        空目录的名字  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */

通用删除接口

c
REMOVE(3)    Linux Programmer's Manual    REMOVE(3)  

NAME  
    remove - remove a file or directory  

SYNOPSIS  
    #include <stdio.h>  
    int remove(const char *pathname);  
    /*  
    @描述:  
        删除文件或空目录  
    @pathname:  
        文件名或空目录名  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */

注意

  • remove删除文件等价于unlink
  • remove删除目录等价于rmdir

文件截短

c
TRUNCATE(2)    Linux Programmer's Manual    TRUNCATE(2)  

NAME  
    truncate, ftruncate - truncate a file to a specified length  

SYNOPSIS  
    #include <unistd.h>  
    #include <sys/types.h>  

    int truncate(const char *path, off_t length);  
    /*  
    @描述:  
        截短文件至指定长度  
    @path:  
        文件名(路径)  
    @length:  
        截短后的长度  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */  

    int ftruncate(int fd, off_t length);  
    /*  
    @描述:  
        截短文件至指定长度  
    @fd:  
        文件描述符  
    @length:  
        截短后的长度  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */

工作路径操作

获取当前工作路径

c
GETCWD(3)    Linux Programmer's Manual    GETCWD(3)  

NAME  
    getcwd, getwd, get_current_dir_name - get current working directory  

SYNOPSIS  
    #include <unistd.h>  

    char *getcwd(char *buf, size_t size);  
    /*  
    @描述:  
        获取进程当前工作路径的绝对路径(最多size字节)  
    @buf:  
        存储路径的字符串指针  
    @size:  
        最大存储字节数(超过size-1报错)  
    @return:  
        成功返回路径首地址,失败返回NULL(errno被设置)  
    */  

    char *getwd(char *buf);  // 已废弃(有越界风险)  

    char *get_current_dir_name(void);  
    /*  
    @描述:  
        获取进程当前工作路径的绝对路径  
    @return:  
        成功返回路径首地址(需手动free),失败返回NULL(errno被设置)  
    */

改变工作路径

c
CHDIR(2)    Linux Programmer's Manual    CHDIR(2)  

NAME  
    chdir, fchdir - change working directory  

SYNOPSIS  
    #include <unistd.h>  

    int chdir(const char *path);  
    /*  
    @描述:  
        改变进程的当前工作路径  
    @path:  
        目标路径字符串  
    @return:  
        成功返回0,失败返回-1(errno被设置)  
    */  

    int fchdir(int fd);  // 已废弃

作业

  1. 仿写ls命令的-a(显示隐藏文件)和-1(单列输出)功能
  2. 仿写cp命令的目录拷贝功能(需递归复制子目录和文件)。

知识如风,常伴吾身