文件和目录的一些函数和命令

函数系列

七种文件类型

普通文件类型 

Linux中最多的一种文件类型, 包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.第一个属性为 [-] 

目录文件 

就是目录, 能用 # cd 命令进入的。第一个属性为 [d],例如 [drwxrwxrwx] 

块设备文件 

块设备文件 : 就是存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。第一个属性为 [b] 

字符设备 

字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。第一个属性为 [c] 

套接字文件 

这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。第一个属性为 [s],最常在 /var/run目录中看到这种文件类型 

管道文件 

FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。第一个属性为 [p] 

链接文件 

类似Windows下面的快捷方式。第一个属性为 [l],例如 [lrwxrwxrwx]

stat

函数原型:

int stat(const char *path, struct stat *buf);

int lstat(const char *path, struct stat *buf);

int fstat(int fd, struct stat *buf);

函数说明:

通过文件名filename获取文件信息,并保存在buf所指的结构体stat中 

lstat读取的链接文件本身的属性

stat读取的是连接文件指向的文件的属性,能追踪,穿透

fstat和第一个函数的区别是通过文件描述符获取文件属性

​ 返回值:

成功返回0,失败返回-1;

文件属性结构体

struct stat {
    dev_t            st_dev;        //文件的设备编号
    ino_t            st_ino;        //节点
    mode_t           st_mode;      //文件的类型和存取的权限
    nlink_t          st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
    uid_t            st_uid;       //用户ID
    gid_t            st_gid;       //组ID
    dev_t            st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
    off_t            st_size;      //文件字节数(文件大小)
    blksize_t        st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
    blkcnt_t         st_blocks;    //块数
    time_t           st_atime;     //最后一次访问时间
    time_t           st_mtime;     //最后一次修改时间
    time_t           st_ctime;     //最后一次改变时间(指属性)
};

 stat结构体中的st_mode 则定义了下列数种情况:

    S_IFMT   0170000    文件类型的位遮罩
    S_IFSOCK 0140000    套接字
    S_IFLNK 0120000     符号连接
    S_IFREG 0100000     一般文件
    S_IFBLK 0060000     区块装置
    S_IFDIR 0040000     目录
    S_IFCHR 0020000     字符装置
    S_IFIFO 0010000     先进先出
​
    S_ISUID 04000     文件的(set user-id on execution)位
    S_ISGID 02000     文件的(set group-id on execution)位
    S_ISVTX 01000     文件的sticky位
​
    S_IRUSR(S_IREAD) 00400     文件所有者具可读取权限
    S_IWUSR(S_IWRITE)00200     文件所有者具可写入权限
    S_IXUSR(S_IEXEC) 00100     文件所有者具可执行权限
​
    S_IRGRP 00040             用户组具可读取权限
    S_IWGRP 00020             用户组具可写入权限
    S_IXGRP 00010             用户组具可执行权限
​
    S_IROTH 00004             其他用户具可读取权限
    S_IWOTH 00002             其他用户具可写入权限
    S_IXOTH 00001             其他用户具可执行权限
​
    上述的文件类型在POSIX中定义了检查这些类型的宏定义:
    S_ISLNK (st_mode)    判断是否为符号连接
    S_ISREG (st_mode)    是否为一般文件
    S_ISDIR (st_mode)    是否为目录
    S_ISCHR (st_mode)    是否为字符装置文件
    S_ISBLK (s3e)        是否为先进先出
    S_ISSOCK (st_mode)   是否为socket
    若一目录具有sticky位(S_ISVTX),则表示在此目录下的文件只能被该文件所有者、此目录所有者或root来删除或改名,在linux中,最典型的就是这个/tmp目录啦。
​

文件属性函数

1. access

函数说明:测试当前用户指定文件是否具有某种属性 

函数原型:int access(const char *pathname, int mode);

参数:
    pathname: 文件名
    mode: 4种权限
        R_OK -- 读 
        W_OK -- 写 
        X_OK -- 执行 
        F_OK -- 文件是否存在

返回值:
    0 - 有某种权限, 或者文件存在
    1 - 没有, 或文件不存在

2. chmod

函数说明:修改文件权限

函数原型:int chmod(const char *filename, int mode);

参数:
    filename: 文件名
    mode: 文件权限, 八进制数

3. chown

函数说明:修改文件所有者和所属组

函数原型:int chown(const char *path, uid_t owner, gid_t group);

函数参数:
    path -- 文件路径
    owner -- 整形值, 用户ID ,通过/etc/passwd查阅
    group -- ....., 组ID,通过/etc/group查阅

4. truncate

函数说明:修改文件大小

函数原型:int truncate(const char *path, off_t length);

参数
    path -- 文件名
    length -- 文件的最终大小
        1. 比原来小, 删掉后边的部分
        2. 比原来大, 向后拓展

5.unlink

函数说明:unlink()函数功能即为删除文件。执行unlink()函数会删除所给参数指定的文件

函数原型:int unlink(const char *pathname);

参数:所删除的指定文件

返回值:成功返回0,失败返回 -1

注意

 执行unlink()函数并不一定会真正的删除文件,它先会检查文件系统中此文件的连接数是否为1,如果不是1说明此文件还有其他链接对象,因此只对此文件的连接数进行减1操作。若连接数为1,并且在此时没有任何进程打开该文件,此内容才会真正地被删除掉。在有进程打开此文件的情况下,则暂时不会删除,直到所有打开该文件的进程都结束时文件就会被删除。

目录操作相关函数

1. 文件重命名

int rename(const char *oldpath, const char *newpath);

2. 修改当前进程(应用程序)的路径 cd

int chdir(const char *path);

参数: 切换的路径

3. 获取当前进程的工作目录 pwd

char *getcwd(char *buf, size_t size);

返回值:
      成功: 当前的工作目录
      失败: NULL
参数:
      buf: 缓冲区, 存储当前的工作目录
      size: 缓冲区大小

4. 创建目录 mkdir

int mkdir(const char *pathname, mode_t mode);

参数:
        pathname: 创建的目录名
        mode: 目录权限, 八进制的数, 实际权限: 
        mode & ~umask

5. 删除一个空目录

int rmdir(const char *pathname);
参数: 空目录的名字

目录遍历相关函数

1. 打开一个目录

DIR *opendir(const char *name);

参数: 目录名

返回值: 指向目录的指针

2. 读目录

struct dirent
{
    ino_t d_ino;                         // 此目录进入点的inode
    ff_t d_off;                             // 目录文件开头至此目录进入点的位移
    signed short int d_reclen; // d_name 的长度, 不包含NULL 字符
    unsigned char d_type;      // d_name 所指的文件类型 
    har d_name[256];           // 文件名

};
d_type
    DT_BLK - 块设备
    DT_CHR - 字符设备
    DT_DIR - 目录
    DT_LNK - 软连接
    DT_FIFO - 管道
    DT_REG - 普通文件
    DT_SOCK - 套接字
    DT_UNKNOWN - 未知
    
函数原型:struct dirent *readdir(DIR *dirp);

参数: opendir的返回值

返回值: 目录项结构体 

具体使用: while((denp=readdir(dp))!=NULL)

3. 关闭目录

int closedir(DIR *dirp);

代码

读取指定目录下普通文件的个数

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>

//定义函数,读指定目录中文件的个数
int get_file_num(const char* root)
{
        int total=0;
        //读目录
        DIR* dir=NULL;
        dir=opendir(root);
        if(dir==NULL)
        {
                perror("opendir error");
                exit(1);
        }

        //循环读目录中的文件
        struct dirent* ptr=NULL;
        while((ptr=readdir(dir))!=NULL)
        {
                //不处理.和..目录
                if(strcmp(".",ptr->d_name)==0|| strcmp("..",ptr->d_name)==0)
                {
                        continue;
                }
                //判断是否是普通文件
                if(ptr->d_type==DT_REG)
                {
                        total++;
                }
                //如果是目录的话,进行递归处理
                if(ptr->d_type==DT_DIR)
                {
                        //求出子目录
                        char path[1024]={0};
                        sprintf(path,"%s/%s",root,ptr->d_name);
                        total+=get_file_num(path);
                }       
        }       
        
        //关闭目录
        close(dir);
        return total;
}       

int main(int argc,const char* argv[])
{
        if(argc<2)
        {
                printf("./a.out path\n");
                exit(1);
        }
        int total=get_file_num(argv[1]);
        printf("%s 目录下普通文件共 %d 个\n",argv[1],total);
        return 0;
}

dup/dup2函数

函数说明:复制文件描述符

dup()和dup2()函数都可以用来复制一个文件描述符
int dup(int oldfd);

参数:oldfd - 要复制的文件描述符

返回值: 新的文件描述符,取最小的且没被占用的文件描述符
dup调用成功后,有两个文件描述符指向同一个文件
            
int dup2(int oldfd, int newfd);
oldfd原来指向文件hello
newfd原来指向文件world
假设newfd已经指向了一个文件,首先断开close与那个文件的连接,newfd指向oldfd指向的文件,这就是文件描述符重定向
注意,如果oldfd和newfd指向同一个文件,那么就不会断开newfd与文件的连接

newfd没有被占用,newfd指向oldfd指向的文件

代码举例

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main(void)
{
        int fd = open("temp", O_RDWR | O_CREAT | O_APPEND, 0664);
        if(fd == -1)
        {
                perror("open");
                exit(1);
        }

        int fd2 = open("temp1", O_RDWR | O_CREAT | O_APPEND, 0664);
        if(fd2 == -1)
        {
                perror("open open");
                exit(1);
        }
        // 复制文件描述符,fd2也指向temp文件
        dup2(fd, fd2);
        // 写文件
        char* p = "hello,world";
        write(fd2, p, strlen(p));
        close(fd2);

        char buf[1024];
        lseek(fd, 0, SEEK_SET);
        read(fd, buf, sizeof(buf));
        printf(" buf = %s\n", buf);
        close(fd);

        return 0;
}

fcntl函数

函数说明:改变已经打开的文件的属性

这是一个变参函数,
复制一个已有的文件描述符
int ret = fcntl(fd, F_DUPFD);

获取/设置文件状态标志
获取文件状态标识 
int flag = fcntl(fd, F_GETFL)
设置文件状态标识
flag = flag | O_APPEND;
fcntl(fd, F_SETFL, flag)

可以更改的几个标识: O_APPEND、O_NONBLOCK (常用)

命令系列

1.使用命令查看文件类型的三种方法

ls -l、file 文件名、stat

2.ls命令

ls -al

常用参数:

-a, –all 列出目录下的所有文件,包括以 . 开头的隐含文件

-i, –inode 印出每个文件的 inode 号

-l 除了文件名之外,还将文件的权限、所有者、文件大小等信息详细列出来

从左到右依次为:inode节点号,文件类型及权限、属主和所归属的组、最近修改时间、文件或目录名

3.stat命令

- File:显示文件名 
- Size:显示文件大小 
- Blocks:文件使用的数据块总数 
- IO Block:IO块大小 
- regular file:文件类型(常规文件) 
- Device:设备编号 
- Inode:Inode号 
- Links:链接数 
- Access:文件的权限 
- Gid、Uid:文件所有权的Gid和Uid。

Linux下的三个时间: 
1. Access Time:简写为atime,表示文件的访问时间。当文件内容被访问时,更新这个时间。
2. Modify Time:简写为mtime,表示文件内容的修改时间,当文件的数据内容被修改时,更新这个时间。 
3. Change Time:简写为ctime,表示文件的状态时间,当文件的状态被修改时,更新这个时间,例如文件的链接数,大小,权限,Blocks数。

我们都知道touch命令是用来创建文件的,其实它的用法还有一个,就是修改文件的时间戳。 

用法: 
-a 或–time=atime或–time=access或–time=use 只更改访问时间。 其实文件的状态时间也会改变。
-m 或–time=mtime或–time=modify  只更改修改时间。 其实文件的状态时间也会改变。

4.查找文件相关命令

(1)在某个目录下查找包含某个字符串的文件

grep -r "zh_CN" ./

(2)find [路径] <表达式>

-name <表达式> 根据文件名查找文件

-iname <表达式> 根据文件名查找文件,忽略大小写

-path <表达式> 根据路径查找文件

-ipath <表达式> 根据路径查找文件,忽略大小写

-amin <分钟> 过去N分钟内访问过的文件

-atime <天数> 过去N天内访问过的文件

-cmin <分钟> 过去N分钟内修改过的文件

-ctime <天数> 过去N天内修改过的文件

-anewer <参照文件> 比参照文件更晚被读取过的文件

-cnewer <参照文件> 比参照文件更晚被修改过的文件

-size <大小> 根据文件大小查找文件,单位b c w k M G

-type <文件类型> 根据文件类型查找文件。b 块设备 c 字符设备 d 目录 p 管道文件 f 普通文件 l 链接 s 端口文件

-user <用户名> 按归属用户查找文件

-uid <uid> 按UID查找文件

-group <群组名> 按归属群组查找文件

-gid <gid> 按GID查找文件

-empty 查找空文件

eg:

#find /usr/ -name '*mycat*'           查询文件名中包含mycat的文件所在路径

#find /usr/ -name 'mycat*'             查询文件名以mycat开头的文件所在路径

#find /usr/ -name '*mycat'             查询文件名以mycat结尾的文件所在路径

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值