Linux文件属性及目录

目录

Linux文件属性及目录

[一、stat、fstat、lstat 获取文件属性](#一、stat、fstat、lstat 获取文件属性)

[二、chown 改变文件所有者(userID)和所属组(groupID)](#二、chown 改变文件所有者(userID)和所属组(groupID))

[三、getuid、getgid 获取用户ID和用户组ID](#三、getuid、getgid 获取用户ID和用户组ID)

[四、access 获取文件权限](#四、access 获取文件权限)

[五、chmod、fchmod 修改文件权限](#五、chmod、fchmod 修改文件权限)

[六、umask 设置权限掩码](#六、umask 设置权限掩码)

[七、link、symlink、readlink 创建硬链接、创建软链接、读取软链接、删除链接文件](#七、link、symlink、readlink 创建硬链接、创建软链接、读取软链接、删除链接文件)

[八、mkdir、rmdir 创建和删除目录](#八、mkdir、rmdir 创建和删除目录)

[九、opendir、readdir和closedir 打开、读和关闭目录](#九、opendir、readdir和closedir 打开、读和关闭目录)

十、getcwd获取当前进程的工作目录

[十一、chdir、fchdir 更改进程当前的工作目录](#十一、chdir、fchdir 更改进程当前的工作目录)

[十二、rename 重命名文件或移动文件](#十二、rename 重命名文件或移动文件)

示例代码


Linux文件属性及目录

该文档介绍了在Linux应用编程中,文件属性的API调用和目录API的调用。以简洁的应用讲解这些API是怎么使用的,帮助您快速上手Linux应用编程。看完希望对您开发有所帮助。

一、stat、fstat、lstat 获取文件属性

cpp 复制代码
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
​
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
//这个函数相比于上面两个,可以看链接文件本身属性
int lstat(const char *pathname, struct stat *buf);

pathname:文件路径

buf:文件属性就记录在struct stat这个结构体里面,我们传入一个这种结构体指针就行。结构体如下:

cpp 复制代码
struct stat
{
    dev_t st_dev; /* 文件所在设备的 ID */
    ino_t st_ino; /* 文件对应 inode 节点编号 */
    mode_t st_mode; /* 文件对应的模式 */
    nlink_t st_nlink; /* 文件的链接数 */
    uid_t st_uid; /* 文件所有者的用户 ID */
    gid_t st_gid; /* 文件所有者的组 ID */
    dev_t st_rdev; /* 设备号(指针对设备文件) */
    off_t st_size; /* 文件大小(以字节为单位) */
    blksize_t st_blksize; /* 文件内容存储的块大小 */
    blkcnt_t st_blocks; /* 文件内容所占块数 */
    struct timespec st_atim; /* 文件最后被访问的时间 */
    struct timespec st_mtim; /* 文件内容最后被修改的时间 */
    struct timespec st_ctim; /* 文件状态最后被改变的时间 */
};

fd:文件描述符

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

二、chown 改变文件所有者(userID)和所属组(groupID)

cpp 复制代码
#include <unistd.h>
​
int chown(const char *pathname, uid_t owner, gid_t group);

pathname:文件路径

owner:修改后的用户ID

group:修改后的用户组ID

(Tips:如果上面两个参数,其中有一个不想修改,使用用来的ID就行,使用stat查询就可以知道原本的ID)

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

(Tips:使用这个函数修改文件ID,在编译运行时需要加sudo来运行,不然很有可能运行失败,原因很复杂)

三、getuid、getgid 获取用户ID和用户组ID

cpp 复制代码
#include <unistd.h>
#include <sys/types.h>
​
uid_t getuid(void);
gid_t getgid(void);

返回值:返回用户ID或用户组ID。

四、access 获取文件权限

cpp 复制代码
#include <unistd.h>
​
int access(const char *pathname, int mode);

pathname:文件路径

mode :有如下值:(Tips:可以使用|进行组合使用)

  • F_OK:检查文件是否存在

  • R_OK:检查文件是否有读权限。

  • W_OK:检查文件是否有写权限。

  • X_OK:检查文件是否有执行权限

返回值:成功返回0,表示用于mode参数中的权限。失败返回-1,表示mode参数中的有一个或多个不满足。

五、chmod、fchmod 修改文件权限

cpp 复制代码
#include <sys/stat.h>
​
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);

pathname:文件路径(Tips:如果是链接文件,这个函数改变的不是这个链接文件的权限,而是改变链接所指向文件的权限)

mode:文件权限,可以使用八进制表示,也可以使用宏,和open中的mode参数一样。

fd:文件描述符。

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

六、umask 设置权限掩码

(Tips:实际权限 = mode & ~umask)

cpp 复制代码
#include <sys/types.h>
#include <sys/stat.h>
​
mode_t umask(mode_t mask);

mask:要设置的权限掩码,与open中的mode参数一样可以使用八进制或宏组合来表示。

返回值:返回旧的权限掩码

(Tips:可以通过ln 源文件 链接文件 来创建硬链接,可以通过ln -s 源文件 链接文件创建软链接)

cpp 复制代码
#include <unistd.h>
​
//创建硬链接
int link(const char *oldpath, const char *newpath);
//创建软链接
int symlink(const char *target, const char *linkpath);
//读取软链接的路径信息,返回读取到的字节数,不能使用read读
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
//删除链接文件或普通文件
int unlink(const char *pathname);

oldpath:源文件路径

newpath:硬链接文件路径,注意不能指定已经存在的路径。

target:源文件路径

linkpath:软链接文件路径,不能是已经存在的路径

buf:存放路径信息

bufsiz:读取大小(字节)

pathname:要删除的文件路径

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

八、mkdir、rmdir 创建和删除目录

cpp 复制代码
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
​
//创建目录
int mkdir(const char *pathname, mode_t mode);
//删除目录
int rmdir(const char *pathname);

pathname:需要创建或删除的目录路径

mode:目录的权限设置,可以使用八进制表示或使用宏组合表示,与open中的mode参数一样。

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

九、opendir、readdir和closedir 打开、读和关闭目录

cpp 复制代码
#include <sys/types.h>
#include <dirent.h>
​
//打开目录,会返回一个DIR类型的结构体指针,叫做目录句柄DIR指针
DIR *opendir(const char *name);
//读目录,返回一个struct dirent结构体指针,遇到目录结尾返回NULL
struct dirent *readdir(DIR *dirp);
//关闭文件,成功返回0,失败返回-1
int closedir(DIR *dirp);

name:要打开的命令路径

dirp:目录句柄DIR指针

返回值struct dirent:结构体内容如下

cpp 复制代码
struct dirent {
    ino_t d_ino; /* inode 编号 */
    off_t d_off; /* not an offset; see NOTES */
    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]; /* 文件名 */
};

十、getcwd获取当前进程的工作目录

cpp 复制代码
#include <unistd.h>
​
char *getcwd(char *buf, size_t size);

buf:存放当前进程工作目录的绝对路径

size:buf缓冲区的大小(字节)

返回值:成功指向buf指针,失败返回NULL

(Tips:如果buf为NULL,size为0,这个函数会自动分配一个合适的缓冲区,并将该缓冲区作为返回值返回)

十一、chdir、fchdir 更改进程当前的工作目录

cpp 复制代码
#include <unistd.h>
​
int chdir(const char *path);
int fchdir(int fd);

path:新的工作目录路径

fd:更改为fd文件描述符所指向的目录

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

十二、rename 重命名文件或移动文件

cpp 复制代码
#include <stdio.h>
​
int rename(const char *oldpath, const char *newpath);

oldpath:原文件路径

newpath:新文件路径

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

示例代码

代码需求:创建一个权限为0755的目录,并在这个目录中创建一个文件。获取这个文件的inod节点值,是否具有可读权限,获取文件的用户ID和组ID。更改文件的权限为用户可读写执行,组用户和其他用户可读和可执行。为该文件创建软链接和硬链接。获取当前进程的工作目录。

下面是我写的参考代码:

cpp 复制代码
/********************************************
 *项目所有的文件名:dir_file.c 
 *作者:SELSL
 *版本:v1.0
 *描述: 1、创建一个目录,目录里面再创建一个文本文件
        2、先获取该文本文件的inod节点和可读权限和用户ID和用户组ID
        3、修改这个文件的权限为本用户可读可写可执行,同组用户和其他用户可读可执行,
        4、文件分别创建软链接和硬链接
        5、获取当前工作目录
 *其他:无
 *论坛:无
 *日志:初版 v1.0 2025/12/22  SELSL创建
 ********************************************/
​
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
​
#define myDir "./my_dir"
#define fileName "test.txt"
​
int main(int argc, const char *argv[])
{
    //创建目录
    int ret = 0;
    ret = mkdir(myDir, 0755);
    if(-1 == ret)
    {
        printf("创建目录失败\n");
        exit(-1);
    }
    printf("目录:%s 创建成功\n", myDir);
​
    //文件路径
    char *pathName = (char *)malloc(sizeof(char) * 20);
    strcat(pathName, myDir);
    strcat(pathName, "/");
    strcat(pathName, fileName);
    //printf("文件路径生成成功\n");
​
    //创建并打开文件
    FILE *fp = NULL;
    fp = fopen(pathName, "a+");
    if(NULL == fp)
    {
        ferror(fp);
        rmdir(myDir);
        exit(-1);
    }
    
    //检查文件是否存在和可读
    ret = access(pathName, F_OK | R_OK);
    if(-1 == ret)
    {
        printf("文件没有读权限或文件不存在\n");
        fclose(fp);
        exit(-1);
    }
    if(0 == ret)
    {
        printf("文件:%s 有读权限\n", pathName);
    }
​
    //获取文件属性,并得到inode节点编号
    struct stat buf;
    ret = stat(pathName, &buf);
    if(-1 == ret)
    {
        printf("文件属性获取失败\n");
        fclose(fp);
        exit(-1);
    }
    printf("成功获取文件:%s 的inode节点编号:%ld\n", pathName, buf.st_ino);
​
    //获取用户ID和组ID
    uid_t uid = 0;
    gid_t gid = 0;
    uid = getuid();
    gid = getgid();
    printf("成功获取文件:%s 的用户ID:%d 和用户组ID:%d\n", pathName, uid, gid);
​
    //修改文件权限
    ret = chmod(pathName, 0755);
    if(-1 == ret)
    {
        printf("权限修改失败\n");
    }
​
​
    //为文件创建硬链接
    char *hardFileName = (char *)malloc(sizeof(char) * 20);
    strcat(hardFileName, myDir);
    strcat(hardFileName, "/");
    strcat(hardFileName, "text_hard");
    ret = link(pathName, hardFileName);
    if(-1 == ret)
    {
        printf("文件:%s 的硬链接 %s 创建失败\n", pathName, hardFileName);
    }
    printf("文件:%s 的硬链接 %s 创建成功\n", pathName, hardFileName);
    
    //为文件创建软链接
    char *softFileName = (char *)malloc(sizeof(char) * 20);
    strcat(softFileName, myDir);
    strcat(softFileName, "/");
    strcat(softFileName, "text_soft");
    ret = symlink(pathName, softFileName);
    if(-1 == ret)
    {
        printf("文件:%s 的硬链接 %s 创建失败\n", pathName, hardFileName);
    }
    printf("文件:%s 的软链接 %s 创建成功\n", pathName, softFileName);
​
    //获取当前进程工作目录
    char *currentWorkPath = getcwd(NULL, 0);
    printf("当前的工作目录为:%s\n", currentWorkPath);
​
    fclose(fp);
​
    return 0;
}
复制代码

代码执行结果

OK,到这里就已经结束了,主要介绍了文件属性的一些API调用,和目录的一些API调用。参考了正点原子的《Linux C 应用编程参考手册》,对它进行了优化,以简洁的语言来描述了这些API的调用。希望对您的开发有所帮助。

相关推荐
倔强的石头1062 小时前
Linux 进程深度解析(五):程序地址空间 —— 进程的独立内存王国
linux·运维·服务器
橙露2 小时前
VMware Workstation Pro 25H2的linux版本,免费分享,下载:全新命名体系 + 深度适配 Linux 内核,虚拟化效率拉满
java·linux·服务器
bing_feilong2 小时前
ubuntu如何开机运行一个python3脚本?
linux·运维·ubuntu
cnnews2 小时前
某讯T1刷armbian
linux·ubuntu·开源·github
bj_zhb2 小时前
git reflog用法
大数据·linux·git·github
秦苒&2 小时前
【C语言指针五】转移表、回调函数、qsort、qsort函数的模拟实现
c语言·开发语言·c#
OnlyEasyCode2 小时前
Linux部署Nginx前后端web教程
linux·前端·nginx
亮子AI2 小时前
【Typescript】未知类型如何处理?
linux·javascript·typescript
旧梦吟2 小时前
脚本网页 C与汇编详解
c语言·css3·html5