zoukankan      html  css  js  c++  java
  • unix下的文件和目录详解以及操作方法

    前言:unix下一切东西都是文件,一共有7种不同的文件,前一篇博客已经讲解的很清楚了,不懂的可以看看这里。当然,博主知道有些朋友比忙,没时间看,那我就简单点讲讲这7种文件都有哪些吧。

    文件类型包括在stat结构的st_mode成员中,下面是这7种文件类型的判断方法:
            宏                                     文件类型
    S_ISREG(m)                 普通文件(is it a regular file?)
    S_ISDIR(m)                  目录文件(directory?)
    S_ISCHR(m)                 字符特殊文件(character device?)
    S_ISBLK(m)                  块特殊文件(block device?)
    S_ISFIFO(m)                管道或FIFO [FIFO (named pipe)?]
    S_ISLNK(m)                  符号链接 [symbolic link? (Not in POSIX.1-1996.)]
    S_ISSOCK(m)               套接字 [socket? (Not in POSIX.1-1996.)]

    当然这些文件都是有访问权限的,很巧这些权限也是在一个叫struct stat这个结构体中

    结构体struct stat中的成员st_mode值包含了对文件的访问权限位,任何类型的文件都有访问权限(access permission)。每个文件有9个访问权限,可以它们分为3类,u表示用户(所有者)、g表示组、o表示其他

    st_mode屏蔽                   含义
    S_IRUSR                       用户读
    S_IWUSR                      用户写
    S_IXUSR                       用户执行

    S_IRGRP                         组读
    S_IWGRP                        组写
    S_IXGRP                       组执行

    S_IROTH                       其他读
    S_IWOTH                      其他写
    S_ICOTH                       其他执行

    那么问题来了既然有权限,我们怎么知道这些权限呢?当然这不是难事,一个access函数就可以解决问题了

    函数描述:按实际用户ID和实际组ID进行访问权限测试
    (1)头文件
             #include <unistd.h>
    (2)函数原型
              int access(const char *path, int amode);
    (3)参数
             a、path:文件路径
             b、amode:
                     F_OK:测试文件是否存在
                     R_OK:测试文件是否可读
                     W_OK:测试文件是否可写
                     X_OK:测试文件是否可执行
    (4)返回值
              成功:0
              失败:-1

    这是access函数的具体用法的代码(argv[1]必须是一个已经存在的文件):

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main(int argc,char **argv)
    {
        if(argc != 2)
        {
            printf("argc must equal to two!
    ");
            exit(1);
        }
    
      if(access(argv[1],F_OK)) //判断文件是否存在
        {
            printf("%s  not existence!
    ",argv[1]);
            exit(1);
        }
    
      if(access(argv[1],R_OK)) //判断文件是否可读
        {
            printf("%s not read permission
    ",argv[1]);
        }
        else
        {
            printf("%s  have read permission
    ",argv[1]);
        }
    
      if(access(argv[1],W_OK))  //判断文件是否可写
        {
            printf("%s not write permission
    ",argv[1]);
        }
        
        else
        {
            printf("%s  have write permission
    ",argv[1]);
      }
      if(access(argv[1],X_OK)) //判断文件是否可执行
        {
            printf("%s not execute permission
    ",argv[1]);
        }
        else
        {
            printf("%s have execute permission
    ",argv[1]);
        }
    
        return 0;
    }
    View Code

     在ubuntu下运行:

    当然了既然有权限,那么我们在创建文件的时候文件权限也是可以自己控制的,umask函数用上场了


    函数描述:为进程设置文件模式创建屏蔽字,并返回之前的值
    (1)头文件: #include <sys/stat.h>
    (2)函数原型: mode_t umask(mode_t cmask);
    (3)参数:
             cmask:(下面9个常量中的若干个按位或构成),例如:S_IRUSR|S_IRGRP //权限就为用户读和组读
               st_mode屏蔽                    含义
                 S_IRUSR                       用户读
                 S_IWUSR                      用户写
                 S_IXUSR                       用户执行

                 S_IRGRP                         组读
                 S_IWGRP                        组写
                 S_IXGRP                        组执行

                 S_IROTH                       其他读
                 S_IWOTH                      其他写
                 S_ICOTH                       其他执行
    (4)返回值:
              成功:之前的文件模式创建屏蔽字

    代码的具体用法如下:

    #include <sys/stat.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <stdlib.h>
    
     #define RRR (S_IRUSR|S_IRGRP|S_IROTH) //设置文件权限为用户读、组读、其他读
     int main(int argc,char *argv[])
     {
         umask(0); //不设置文件屏蔽字
         creat("text",RRR); //以用户读、组读、其他读的权限创建文件text.txt //这里也可以用open
         
         umask(S_IRUSR|S_IRGRP); //创建用户读、组出屏蔽字
         creat("text1",RRR);   //最后创建出来的文件只有其他读的权限 
         return 0;
     }
    View Code

     既然文件可以创建,当然目录也是可以创建的,mkdir函数就是为创建目录而生的:

    函数描述:创建一个空目录,.和..自动创建
    (1)头文件
              #include <sys/stat.h>
    (2)函数原型
              int mkdir(const char *path, mode_t mode);
    (3)参数:
              a、path:文件名
              b、mode:是以下15种常量的按位或
                      mode                     含义
                    S_ISUID               执行时设置用户ID
                    S_ISGID               执行时设置组ID
                    S_ISVTX               保存正文(粘着位)

                    S_IRWXU             用户(所有者)、读、写和执行
                    S_IRUSR              用户(所有者)读
                    S_IWUSR             用户(所有者)写
                    S_IXUSR              用户(所有者)执行

                    S_IRWXG             组读、写和执行
                    S_IRGRP              组写
                    S_IWGRP             组读
                    S_IXGRP              组执行

                    S_IRWXO            其他读、写和执行
                    S_IROTH             其他读
                    S_IWOTH            其他写
                    S_IXOTH             其他执行
    (4)返回值
             成功:0
             失败:-1

    创建目录的具体实现:

    #include <sys/stat.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    int main(int argc,char *argv[])
    {
        if(mkdir("test.txt",S_IWOTH|S_IRUSR|S_IRGRP) == -1) /*以其他写、用户读、组读权限创建一个空目录*/
        {
            perror("mkdir");
            exit(1);
        }
        return 0;
    }
    View Code

     umask函数是在创建文时设置权限,那么在文件被创建之后还能修改权限吗?这时候chmod函数就派上用处了

    (1)头文件        #include <sys/stat.h>

    (2)函数原型     int chmod(const char *path, mode_t mode);

     (3)参数:

              a、path:文件路径

              b、mode:跟上面midir函数中的成员mode一样,其中的宏位或就可以了

    改变文件权限的例子:

    chmod("text",S_IRUSR|S_IRGRP|S_IROTH);    //把text文件的权限改为用户读、组读、其他读

     既然权限可以改变权限,当然改个名字也是没问题的,用rename函数轻松解决问题:

    (1)头文件     #include <stdio.h>

    (2)函数原型   int rename(const char *old, const char *new);

    (3)参数:

              a、old:文件原来的名字

              b、new:新的名字

    (4)返回值:

             成功:0

             失败:-1

     改变文件名字的例子:

    rename("text","hhtext"); //将名字为text的文件改为hhtext

    其实文件中还有个小操作就是可以在任何位置截断文件中的内容:

    truncate("test",3);    //将文件test长度截断为3字节

    好了讲了那么多关于文件的权限的东西,是时候讲讲怎么打开一个目录和读目录中的的东西了:

     读目录中,要经过三步:打开目录、读目录、关闭目录,对应用到的函数分别为opendir、readdir、closedir。
     
     一、打开目录
    (1)头文件
          #include <sys/types.h>
          #include <dirent.h>2)函数原型
          DIR *opendir(const char *name);
    (3)参数
          name:目录名
    (4)返回值:
         成功:返回一个DIR*型的目录流
         失败:NULL
          
    二、读目录
    (1)头文件
         #include <dirent.h>2)函数原型
         struct dirent *readdir(DIR *dirp);
    (3)参数
          a、dirp:调用opendir函数后返回的DIR*类型的目录流
    (4)返回值:
         成功:返回一个(struct dirent)型的结构体
         下面是struct dirent结构体的具体内容
            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 supportedby all file system types */
                   char           d_name[256]; 文件名 /* filename */
               };
            struct 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    命名管道或FIFO(This is a named pipe (FIFO).)
               DT_LNK     符号连接(This is a symbolic link.)
               DT_REG     普通文件(This is a regular file.)
               DT_SOCK    UNIX域套接字( This is a UNIX domain socket.)
               DT_UNKNOWN  未知类型(The file type is unknown.)
         读完或者失败都返回NULL
    
    三、关闭目录
    (1)头文件
          #include <sys/types.h>
          #include <dirent.h>2)函数原型
          int closedir(DIR *dirp);
    (3)参数
         a、dirp:用opendir函数后返回的DIR*类型的目录流
    (4)返回值:
          成功:0
          失败:-1
         
    四、更改当前工作路径
    (1)头文件    #include <unistd.h>2)函数原型  int chdir(const char *path);
    (3)参数:
          a、path:需要更改的路径
    (4)返回值
          成功:0
          失败:-1
    例子:
        chdir("/test.txt"); //当前工作目录更改到test.txt中
            
    五、获得当前工作目录完整的绝对路径
    (1)头文件     #include <unistd.h>2)函数原型   char *getcwd(char *buf, size_t size);
    (3)参数:
         a、buf:存放绝对路径的缓冲区
         b、size: 缓冲区的大小
    (4)返回值:
         成功:返回当前工作目录完整的绝对路径
         失败:NULL
    例子:
         char buf[100];
         bzero(buf,sizeof(buf));
         if(getcwd(buf,sizeof(buf)) == NULL)
           {
             perror("getcwd");
             exit(1);
           }     
         

     打开一个目录然后读目录中的文件并把文件名打印出来,具体代码如下:

    #include <stdio.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <stdlib.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    void open_file(char *name)
    {
        DIR * entry; //opendir返回值
        struct dirent *ep; //readdir返回值
        char path_name[100];
        
        if((entry = opendir(name)) == NULL)
        {
            perror("opendir");
            exit(1);
        }
        
        while(1)
        {
           if((ep = readdir(entry)) == NULL)
           {
               break;
           }
           if(ep->d_name[0] == '.') //去掉隐藏文件
           {
               continue;
           }
          
            sprintf(path_name,"%s/%s",name,ep->d_name); //拼接两个字符
            printf("%s
    ",path_name); //输出路径
           
           if(ep->d_type & DT_DIR) //目录  也可以用lstat/stat函数
           {   
               open_file(path_name); //递归打开下一目录
           }
           
        }
        
        closedir(entry);
    }
    int main(int argc,char *argv[])
    {
        if(argc != 2)
        {
            printf("argv[1] have to a directory!
    ");
            exit(1);
        }
        open_file(argv[1]);
        return 0;
    }
    View Code

     运行程序的效果图如下:

     最后来点小知识:

    **每个文件系统所在的设备都有主、次设备号表示
    **设备号所用的数据类型是基本系统数据类型dev_t
    **我们通常可以使用两个宏:major、minor来访问主、次设备号
    **系统中与每个文件名关联的st_dev值是文件系统的设备号,该文件包括了这一文件名以及与其对应的i节点
    **只有字特殊文件和块特殊文件的才有st_rdev值。此值包括实际设备的设备号

    具体代码如下:

    #include <sys/stat.h>
    #include <stdio.h>
    #include <errno.h>
    #include <stdlib.h>
    
    int main(int argc,char *argv[])
    {
        int i;
        struct stat buf;
        for(i=1;i<argc;i++)
        {
            printf("%s:",argv[i]);
            if(stat(argv[i],&buf) == -1){
                perror("stat");
                exit(1);
            }
            
            printf("dev = %d/%d",major(buf.st_dev),minor(buf.st_dev));
            //判断是否是字特殊文件(S_ISCHR)块特殊文件(S_ISCHR)
            if(S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)){
                printf(" (%s) rdev = %d/%d",
                (S_ISCHR(buf.st_mode)) ? "character" : "block",
                major(buf.st_rdev),minor(buf.st_rdev));
            }
            printf("
    ");
        }
        return 0;
    }
    View Code

    运行结果:

  • 相关阅读:
    js中关于undefined值的判断
    解决flexpaper搜索文字时不能高亮的问题
    计算出当月还剩下几天
    仿新浪微博返回顶部的js实现(jQuery/MooTools)
    使用Javascript计算时间差和计算日期加天数后的日期值
    小tip:iframe高度动态自适应
    JQuery之ContextMenu(右键菜单)
    JS的split函数用法
    jquery context menu用法
    jQuery实现搜索关键字自动匹配提示方法
  • 原文地址:https://www.cnblogs.com/wurenzhong/p/7532537.html
Copyright © 2011-2022 走看看