04目录操作与文件属性

一、Linux 系统的目录结构

Linux系统的一个目录中包含多个目录项,每个目录项中包含一个I-Node结点与目录文件名一,一对应.

二、linux 系统目录操作

1.打开目录 -> 2.读取目录 -> 3.关闭目录

1、opendir 打开目录

man 3 opendir 查看目录打开函数

NAME
       opendir, fdopendir - open a directory

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

       DIR *opendir(const char *name);
           name:需要打开的目录路径名 
           返回值:成功  目录指针   失败  NULL
       
       
例子:打开一个目录
DIR *dp = opendir("./mydir");
if (dp == NULL)
{
    printf("打开目录失败\n");
    return -1;
}       

2、readdir 读取目录项信息

 man 3 查看读取目录项函数

NAME
       readdir - read a directory

SYNOPSIS
       #include <dirent.h>

       struct dirent *readdir(DIR *dirp);
       dirp:需要读取的目录指针 
       返回值:成功  目录项信息结构体  
              失败  NULL 
              
目录项信息结构体
struct dirent {
     ino_t          d_ino;       /* Inode number I-NODE节点号*/
     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   ⭐文件名*/
};
  
例子:读取目录项
struct dirent *p = readdir(dp);
printf("文件名 %s\n",p->d_name);     

例子:判断文件类型 
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 could not be determined.    不知道啥类型      
            
struct dirent *p = readdir(dp);
if(p->d_type == DT_DIR)  //判断是否为目录 
...
if(p->d_type == DT_REG) //判断是否为普通文件 
.....
         

3、closedir 关闭一个目录

NAME
       closedir - close a directory

SYNOPSIS
       #include <sys/types.h>

       #include <dirent.h>
       int closedir(DIR *dirp);

4、创建与删除目录

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:权限  👉0777 
       返回值:成功  0  失败  -1 
       
       
NAME
       rmdir - delete a directory
                删除一个空目录 
SYNOPSIS
       #include <unistd.h>
       int rmdir(const char *pathname);      
        pathname:需要删除的目录名称 
      
int rename(const char *oldpath, const char *newpath);   //重命名一个文件 

int unlink(const char *pathname);       //删除断开一个文件链接
        

5、stat 文件属性获取(了解)

man 2 stat 查看文件属性函数

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);
       

文件属性结构体  
  struct stat {
               dev_t     st_dev;         /* ID of device containing file 设备ID */
               ino_t     st_ino;         /* Inode number  i-node节点 */
               mode_t    st_mode;        /* File type and mode  文件类型与权限 */
               nlink_t   st_nlink;       /* Number of hard links 硬链接数 */
               uid_t     st_uid;         /* User ID of owner   用户ID */
               gid_t     st_gid;         /* Group ID of owner  用户组ID*/
               dev_t     st_rdev;        /* Device ID (if special file) 设备ID */
               off_t     st_size;        /* Total size, in bytes 文件大小 */
               blksize_t st_blksize;     /* Block size for filesystem I/O  建议操作(read/write)文件时的大小*/
               blkcnt_t  st_blocks;      /* Number of 512B blocks allocated 以512字节给文件分配块数 */


               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 最后一次状态变更*/

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };       
                

获取设备id

unsigned int major(dev_t dev);  //获取驱动主设备号
unsigned int minor(dev_t dev);  //获取驱动次设备号         
printf("ID of containing device:  [%jx,%jx]\n",
(uintmax_t)major(sb.st_dev),
(uintmax_t)minor(sb.st_dev));
linux系统下只有驱动设备才有设备ID ,普通文件是没有设备ID的 

文件权限获取

#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysmacros.h>

int main(int argc, char *argv[])
{
    // 定义结构体变量
    struct stat sb;

    if (argc != 2) // 判断参数是否正确
    {
        // 把argv[0]输出到标准出错设备中
        fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
        exit(EXIT_FAILURE); // 结束进程
    }

    if (stat(argv[1], &sb) == -1)
    {
        perror("stat"); // 打印错误信息
        exit(EXIT_FAILURE);
    }

    // 输出文件权限
    printf("Mode:                     %jo (octal)\n", (uintmax_t)sb.st_mode);

    unsigned short mode = sb.st_mode & 0x1ff; // 提取后9位

    int stack[10] = {0}; // 栈

    for (int i = 0; i < 9; i++)
    {
        stack[i] = mode & 0x01;
        mode >>= 1;
    }

    // 遍历栈中的数据
    for (int i = 8; i >= 0; i--)
    {
        printf("%d\t", stack[i]);
    }
}

EXAMPLES 官方使用例子

#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysmacros.h>

int  main(int argc, char *argv[])
{
           struct stat sb;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           if (lstat(argv[1], &sb) == -1) {
               perror("lstat");
               exit(EXIT_FAILURE);
           }

           printf("ID of containing device:  [%jx,%jx]\n",
                   (uintmax_t) major(sb.st_dev),
                   (uintmax_t) minor(sb.st_dev));

           printf("File type:                ");

           switch (sb.st_mode & S_IFMT) {
           case S_IFBLK:  printf("block device\n");            break;
           case S_IFCHR:  printf("character device\n");        break;
           case S_IFDIR:  printf("directory\n");               break;
           case S_IFIFO:  printf("FIFO/pipe\n");               break;
           case S_IFLNK:  printf("symlink\n");                 break;
           case S_IFREG:  printf("regular file\n");            break;
           case S_IFSOCK: printf("socket\n");                  break;
           default:       printf("unknown?\n");                break;
           }

           printf("I-node number:            %ju\n", (uintmax_t) sb.st_ino);
           printf("Mode:                     %jo (octal)\n",
                   (uintmax_t) sb.st_mode);
           printf("Link count:               %ju\n", (uintmax_t) sb.st_nlink);
           printf("Ownership:                UID=%ju   GID=%ju\n",
                   (uintmax_t) sb.st_uid, (uintmax_t) sb.st_gid);
            printf("Preferred I/O block size: %jd bytes\n",
            (intmax_t) sb.st_blksize);
            printf("File size:                %jd bytes\n",
            (intmax_t) sb.st_size);
            printf("Blocks allocated:         %jd\n",
            (intmax_t) sb.st_blocks);
            printf("Last status change:       %s", ctime(&sb.st_ctime));
            printf("Last file access:         %s", ctime(&sb.st_atime));
            printf("Last file modification:   %s", ctime(&sb.st_mtime));

           exit(EXIT_SUCCESS);
}

至此,希望看完这篇文章的你有所收获,我是Bardb,译音八分贝,道友,下期见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bardb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值