Linux应用:文件属性

linux中各种文件类型

在 Linux 系统中,文件类型决定了文件的性质和用途。内核通过文件类型管理不同的资源访问方式,
常见的文件类型包括:

普通文件(Regular File)

定义:存储数据的常规文件,分为文本文件和二进制文件。
特点:可读写,具有确定的文件大小,支持随机访问。
示例:.txt文本文件、.c源代码文件、.so共享库文件。
文件描述符操作:通过open函数获取文件描述符后,使用read/write进行读写,与其他文件类型的操作方式一致。

目录文件(Directory)

定义:用于组织文件系统层级结构的特殊文件。
特点:包含其他文件和子目录的元数据,不可直接写入数据。
示例:/home、/etc等目录。
文件描述符操作:通过opendir函数打开目录获取DIR指针(非文件描述符),使用readdir遍历条目。若需对目录本身操作(如创建 / 删除),需通过mkdir/rmdir等系统调用。

符号链接(Symbolic Link)

定义:指向其他文件或目录的快捷方式。
特点:内容为目标路径字符串,大小通常为目标路径长度。
示例:ln -s target.txt link.txt创建的链接文件。
文件描述符操作:通过open打开符号链接时,内核自动解析为目标文件的文件描述符。若需操作符号链接本身(如删除),需使用unlink函数。

设备文件(Device File)

定义:代表硬件设备的文件,分为块设备和字符设备。
特点:
块设备:以块为单位读写(如磁盘),支持随机访问。
字符设备:按字符流读写(如串口),通常不支持随机访问。
示例:/dev/sda(磁盘)、/dev/tty(终端)。
文件描述符操作:通过open获取文件描述符后,使用read/write直接与硬件交互。例如,向/dev/null写入数据会被丢弃。

套接字文件(Socket)

定义:用于进程间通信(IPC)或网络通信的特殊文件。
特点:不存储数据,仅作为通信端点。
示例:网络套接字(AF_INET)、本地套接字(AF_UNIX)。
文件描述符操作:通过socket函数创建套接字文件描述符,使用bind、listen、accept等函数进行网络编程。

命名管道(FIFO)

定义:进程间通信的管道文件,支持单向数据流。
特点:数据先进先出,仅在内存中存在。
示例:mkfifo myfifo创建的管道文件。
文件描述符操作:通过open打开 FIFO 文件描述符后,可像普通文件一样读写,但需注意阻塞行为(默认情况下,读操作会等待写端打开)。

识别文件类型的方法

命令行工具:
ls -l:通过第一个字符识别类型(如-为普通文件,d为目录,l为符号链接)。
file:自动检测文件类型(如file test.txt显示 “ASCII text”)。
编程方法:
使用stat系统调用获取文件元数据,通过st_mode字段判断类型:

#include <sys/stat.h>
#include <stdio.h>

int main() {
    struct stat file_info;
    if (stat("test.txt", &file_info) == -1) {
        perror("stat");
        return 1;
    }
    if (S_ISREG(file_info.st_mode)) {
        printf("普通文件\n");
    } else if (S_ISDIR(file_info.st_mode)) {
        printf("目录\n");
    }
    return 0;
}

权限管理基础

Linux 文件权限针对三类用户角色:
属主(Owner):文件的所有者。
属组(Group):文件所属的用户组。
其他用户(Others):不属于上述两类的用户。
每个角色拥有三种基本权限:
读(r):允许查看文件内容(对目录为列出文件列表)。
写(w):允许修改或删除文件内容(对目录为创建、移动或删除文件)。
执行(x):允许运行程序或进入目录(对目录为使用cd命令进入)。
权限信息通过ls -l命令查看,以-rwxr-xr–为例:
第一位-表示普通文件(d为目录,l为符号链接)。
后续九位分为三组,依次对应属主、属组、其他用户的权限。

文件与目录的权限差异

文件
默认权限:创建时为rw-(属主可读可写,其他无权限)。
执行权限:仅对二进制文件或脚本有效,允许内核加载并执行。
目录
默认权限:创建时为rwx(所有用户可读、写、执行)。
特殊逻辑:
读权限:允许列出目录内容,但无法查看文件详细信息(如ls -l)。
写权限:允许创建、删除文件,但删除操作实际依赖文件的属主权限。
执行权限:允许进入目录(cd)或查看文件详细信息。

权限修改命令

chmod:修改文件或目录权限

chmod 640 file.txt  # 属主rw(6)、属组r(4)、其他无(0

数字模式
通过八进制数字组合设置权限(r=4, w=2, x=1)

chmod u+w,g-x file.txt  # 属主添加写权限,属组移除执行权限
chmod a=rwx dir/        # 所有用户赋予读写执行权限

字母模式(角色 + 操作符)
使用u(属主)、g(属组)、o(其他)、a(所有)指定目标角色,配合+(添加)、-(移除)、=(覆盖)操作

chmod -R 755 project/   # 目录属主rwx,属组和其他r-x

递归修改目录
使用-R选项递归处理子目录及文件

chown:修改属主和属组

chown user file.txt          # 修改属主为user
chown user:group file.txt    # 同时修改属主和属组
chown -R root:admin logs/    # 递归修改目录及其内容的属主和属组

chgrp:修改属组

chgrp developers code.py     # 修改属组为developers

高级技巧与注意事项

特殊权限:
Setuid(s):可执行文件运行时临时拥有属主权限(如/usr/bin/passwd)。
Setgid(s):目录中创建的文件继承目录属组。
Sticky Bit(t):仅允许文件属主删除文件(如/tmp目录)。
默认权限掩码(umask):
用户创建文件时,实际权限为666 - umask,目录为777 - umask。
查看当前掩码:umask(默认值通常为0022)。
参考文件权限:
使用–reference选项复制其他文件的权限:

chmod --reference=template.txt target.txt

检测文件权限(access 函数)

access函数用于检查调用进程是否具有对文件的特定访问权限(如读、写或执行)。其函数原型为:

#include <unistd.h>
int access(const char *pathname, int mode);

pathname:文件路径。
mode:权限检查类型,可组合以下标志:
F_OK:检查文件是否存在。
R_OK:检查是否可读。
W_OK:检查是否可写。
X_OK:检查是否可执行。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *file = "data.txt";

    // 检查文件是否存在
    if (access(file, F_OK) == -1) {
        perror("文件不存在");
        exit(EXIT_FAILURE);
    }

    // 检查是否有读权限
    if (access(file, R_OK) == 0) {
        printf("可读\n");
    }

    // 检查是否有写权限
    if (access(file, W_OK) == 0) {
        printf("可写\n");
    }

    return 0;
}

access返回 0 表示检查通过,返回 - 1 表示权限不足或文件不存在。
需结合errno判断具体错误原因(如ENOENT表示文件不存在)。
基于实际用户 ID:access的权限判断基于进程的实际用户 ID(Real UID),而非有效用户 ID(Effective UID)。这与open等函数的行为不同(后者基于有效用户 ID)。

chmod 函数

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

int main() {
    const char *filename = "test.txt";
    mode_t new_mode = 0644;  // 属主 rw-, 属组 r--, 其他 r--

    // 修改文件权限
    if (chmod(filename, new_mode) == -1) {
        perror("chmod");
        exit(EXIT_FAILURE);
    }

    printf("文件权限已修改为 %o\n", new_mode);
    return 0;
}

头文件:
sys/stat.h:包含 chmod 和 mode_t 的定义。
stdio.h、stdlib.h、string.h:用于输入输出和错误处理。
函数参数:
filename:要修改权限的文件路径。
new_mode:新权限的八进制表示(如 0644 对应 rw-r–r–)。
错误处理:
chmod 返回 -1 表示失败,通过 perror 打印错误信息。

chmodat

#include <fcntl.h>
#include <unistd.h>

int dir_fd = open("/path/to/dir", O_RDONLY);
if (dir_fd == -1) { /* 错误处理 */ }

// 修改目录内文件的权限(相对于 dir_fd)
if (chmodat(dir_fd, "file.txt", 0644, 0) == -1) {
    perror("chmodat");
}
close(dir_fd);

权限掩码(umask):
新权限会受当前进程 umask 的影响(实际权限 = new_mode & ~umask)。
例如:若 umask 为 0022,设置 0666 会实际生效为 0644。
特殊权限:
可通过 | 运算符设置特殊权限:

mode_t mode = 0755 | S_ISUID;  // 添加 Setuid 权限(rwsr-xr-x)

符号链接处理:
chmod 默认修改符号链接指向的目标文件权限。
若需直接修改符号链接本身的权限,需结合 fchmodat 和 AT_SYMLINK_NOFOLLOW 标志。

fchmodat

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

int main() {
    const char *link_path = "symlink.txt";
    const char *target_path = "target.txt";

    // 创建符号链接
    if (symlink(target_path, link_path) == -1) {
        perror("symlink");
        exit(EXIT_FAILURE);
    }

    // 修改符号链接本身的权限(不跟随目标)
    if (fchmodat(AT_FDCWD, link_path, 0777, AT_SYMLINK_NOFOLLOW) == -1) {
        perror("fchmodat");
        exit(EXIT_FAILURE);
    }

    printf("符号链接权限已设置为 777\n");
    return 0;
}

使用 chmod 函数可方便地修改文件权限,需注意 umask 和特殊权限的影响。

  • 对于符号链接或复杂路径操作,优先使用 chmodat 或 fchmodat 以增强控制。
  • 始终进行错误检查,确保权限修改成功。

umask 介绍

umask 是 Linux 系统中用于控制新创建文件和目录默认权限的掩码。它决定了在创建文件或目录时,从默认权限中去除哪些权限位。umask 的值是一个八进制数,与文件和目录的权限位相对应。
umask 的工作机制
当用户创建一个文件或目录时,系统会先根据默认的权限模式(文件通常是 666,目录通常是 777),然后与 umask 进行按位取反的 “与” 操作,得到最终的实际权限。例如,umask 的值为 022,对于文件来说:
默认权限 666(八进制)转换为二进制是 110 110 110。
umask 022 转换为二进制是 000 010 010,取反后为 111 101 101。
进行按位 “与” 操作:(110 110 110) & (111 101 101) = 110 100 100,转换回八进制就是 644,这就是新创建文件的实际权限。对于目录,默认权限 777(111 111 111)与 umask 取反按位 “与” 后得到 755(111 101 101)。

目录文件

opendir:打开目录并返回DIR指针。

#include <dirent.h>
DIR *opendir(const char *dirname);

成功返回DIR指针,失败返回NULL。

readdir:读取目录条目

struct dirent *readdir(DIR *dirp);

返回struct dirent结构体指针,包含文件名和文件类型等信息。
遍历结束或出错时返回NULL。

closedir:关闭目录流。

int closedir(DIR *dirp);

遍历目录内容

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main() {
    DIR *dir;
    struct dirent *entry;
    const char *dirname = ".";

    // 打开目录
    dir = opendir(dirname);
    if (dir == NULL) {
        perror("opendir");
        exit(EXIT_FAILURE);
    }

    // 遍历目录条目
    while ((entry = readdir(dir)) != NULL) {
        printf("文件名: %s\n", entry->d_name);
        printf("文件类型: ");
        switch (entry->d_type) {
            case DT_REG: printf("普通文件\n"); break;
            case DT_DIR: printf("目录\n"); break;
            case DT_LNK: printf("符号链接\n"); break;
            default: printf("未知类型\n");
        }
    }

    // 关闭目录
    closedir(dir);
    return 0;
}

过滤隐藏文件

while ((entry = readdir(dir)) != NULL) {
    if (entry->d_name[0] == '.')  // 跳过隐藏文件
        continue;
    // 处理可见文件
}

获取详细文件信息

结合stat函数获取文件属性(如大小、修改时间):

struct stat file_stat;
char path[256];

while ((entry = readdir(dir)) != NULL) {
    snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
    if (stat(path, &file_stat) == -1) {
        perror("stat");
        continue;
    }
    printf("文件大小: %ld bytes\n", file_stat.st_size);
}

scandir:按名称排序并过滤条目。

#include <dirent.h>
int scandir(const char *dir, struct dirent ***namelist, 
            int (*filter)(const struct dirent *),
            int (*compar)(const struct dirent **, const struct dirent **));

ftw:递归遍历目录树。

#include <ftw.h>
int ftw(const char *dir, int (*fn)(const char *, const struct stat *, int), int nopenfd);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/983940.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1.5.1 掌握Scala内建控制结构 - 条件表达式

本文介绍了 Scala 中条件表达式的使用及其在实际任务中的应用。条件表达式的语法为 if (条件) 值1 else 值2&#xff0c;其结果类型取决于值1和值2的类型。如果类型相同&#xff0c;结果类型与它们相同&#xff1b;如果不同&#xff0c;则结果类型为 Any。通过两个任务展示了条…

Linux rootfs:如何开机就自动添加某个用户?

前言 项目开发需求&#xff0c;需要开机后就自动创建某个用户密码 厂家提供的sdk&#xff0c;只有adduser命令&#xff0c; 该命令添加用户时&#xff0c;会有终端交互&#xff0c; 需要手动输入2次密码&#xff0c; 所以无法通过简单脚本方式创建。 要实现自动填充密码&…

计算机三级网络技术知识点汇总【7】

第七章 路由器配置及使用 1. 路由器的基础知识 1.1 路由器的基本概念 路由器是工作在网络层的设备&#xff0c;负责将数据分组从源端主机经最佳路径传送到目的端主机&#xff0c;实现在网络层的互联。路由器工作在 TCP/IP 网络模型的网络层&#xff0c;对应于 OSI 网络参考模…

Compounding Geometric Operations for Knowledge Graph Completion(论文笔记)

CCF等级&#xff1a;A 发布时间&#xff1a;2023年7月 25年3月10日交 一、简介 使用知识图谱嵌入模型&#xff0c;将三元组&#xff08;h,r,t&#xff09;中关系 r 转化为平移、旋转、缩放矩阵对头节点以及尾节点进行运算&#xff0c;判定三元组的真实性。 二、原理 1.整…

mac系统安装

目录 准备工作 一、安装虚拟机 二、解锁系统 三、安装系统 四、部署系统 五、安装VMware Tools(选做) 为什么要安装VMware Tools,这是啥玩意? 六、配置共享文件夹(选做) 为什么要共享文件夹? 注意事项: 七、安装完成 准备工作 一、安装说明: 本教程分为7个部…

DNASimCLR:一种基于对比学习的基因序列数据分类的深度学习方法

摘要 DNASimCLR利用卷积神经网络和基于对比学习的SimCLR框架&#xff0c;从不同的微生物基因序列中提取复杂的特征。在包含宏基因组和病毒基因序列的两个经典的大规模未标记数据集上进行了预训练。后续的分类任务通过使用先前获得的模型对预训练的模型进行微调来完成。我们的实…

Ae 效果详解:VR 旋转球面

Ae菜单&#xff1a;效果/沉浸式视频/VR 旋转球面 Immersive Video/VR Rotate Sphere VR 旋转球面 VR Rotate Sphere效果用于对 VR 视频进行三轴旋转&#xff0c;以调整视频的视角方向。可用于校正拍摄时的角度偏差&#xff0c;或者根据创意需求模拟摄像机旋转。 本效果适用于所…

南开提出1Prompt1Story,无需训练,可通过单个连接提示实现一致的文本到图像生成。

&#xff08;1Prompt1Story&#xff09;是一种无训练的文本到图像生成方法&#xff0c;通过整合多个提示为一个长句子&#xff0c;并结合奇异值重加权&#xff08;SVR&#xff09;和身份保持交叉注意力&#xff08;IPCA&#xff09;技术&#xff0c;解决了生成图像中身份不一致…

Python----数据可视化(Seaborn二:绘图一)

常见方法 barplot方法 单独绘制条形图 catplot方法 可以条形图、散点图、盒图、小提亲图、等 countplot方法 统计数量 一、柱状图 seaborn.barplot(dataNone, xNone, yNone, hueNone, colorNone, paletteNone) 函数描述data用于绘图的数据集。x用于绘制长格式数据的输入。…

只音 1.2.0 |纯净无广告,畅听全网音乐,支持无损下载和批量下载

只音是一款全网音乐一网打尽的听歌利器&#xff0c;无需登录即可搜索抖音、网易云、QQ音乐等平台资源&#xff0c;无损音质直连播放。内置智能推荐算法&#xff0c;每日更新热门榜单与个性化歌单&#xff0c;轻松发现小众优质音乐。支持批量下载功能&#xff0c;一次性打包30首…

Python从入门到精通1:FastAPI

引言 在现代 Web 开发中&#xff0c;API 是前后端分离架构的核心。FastAPI 凭借其高性能、简洁的语法和自动文档生成功能&#xff0c;成为 Python 开发者的首选框架。本文将从零开始&#xff0c;详细讲解 FastAPI 的核心概念、安装配置、路由设计、请求处理以及实际应用案例&a…

Service与Ingress:如何将你的应用暴露给世界

引言&#xff1a;从“内部通讯”到“对外开放” 想象Kubernetes集群是一座繁忙的办公楼&#xff0c;每个Pod&#xff08;容器&#xff09;是楼内的员工。 Service 就像前台的接待员&#xff0c;负责将外部电话&#xff08;请求&#xff09;转接到正确的员工&#xff08;Pod&am…

【Linux学习篇】--开发工具第一期

目录 1. Linux编辑器的使用--vim使用 1.1 vim的基本概念 1.2 vim基本操作 1.3 vim正常模式&#xff08;指令模式&#xff09;命令集 1.4 vim末行模式命令集 1.5 vim配置 2. Linux编译器-gcc/g使用 2.1 背景知识 2.2 gcc如何完成 2.3 gcc选择项 1. Linux编…

Elastic:AI 会开始取代网络安全工作吗?

作者&#xff1a;来自 Elastic Joe DeFever 不会&#xff0c;但它正在从根本上改变这些工作。 生成式 AI (GenAI) 正迅速成为日常安全工作流程中的一个重要组成部分。那么&#xff0c;它是合作伙伴还是竞争对手&#xff1f; GenAI 技术在安全堆栈几乎每个方面的广泛应用&#…

Windows 11 IoT 企业版 LTSC 2025 特制适度 22635.5025

文件: Windows 11 IoT 企业版 LTSC 2025 特制适度 22635.5025 install.esd 大小: 2.57G&#xff08;2768694310 字节&#xff09; 修改时间: 2025年3月9日, 星期日, 11 : 40 : 15 MD5: BFCB23BC2F78CA9243FFA68D5DDDDFC1 SHA1: C4D8BBF8B8D8E0E8E49DE5E9CC8D7F77385A745A CRC32…

Lab18_ SQL injection with filter bypass via XML encoding

文章目录 前言&#xff1a;进入实验室构造 payload 前言&#xff1a; 实验室标题为&#xff1a; 通关 XML 编码绕过过滤器的 SQL 注入 简介&#xff1a; 此实验室的库存检查功能中存在 SQL 注入漏洞。查询结果在应用程序的响应中返回&#xff0c;因此您可以使用 UNION 攻击…

kali虚拟机登录页面发癫 大写锁定输入不了密码

不知道怎么了 总是发癫 重启切换太麻烦了 还有时候不成功 kali其实可以开启虚拟键盘 如下 就解决的 发癫kali 发癫 发癫

【汇编语言】单片机程序执行过程

一、任务需求 指示灯LED4闪烁&#xff0c;亮0.5秒&#xff0c;灭0.5秒&#xff0c;无限循环 二、针对硬件的编程 1、确定原理图2、确定硬件的物理关系 三、设计步骤 1.用自己的语言描述工作流程 1.1指示灯LED4亮1.2延时0.5秒1.3指示灯LED4灭1.4延时0.5秒1.5跳转到1.1步 …

【Linux篇】调试器-gdb/cgdb使用

&#x1f4cc; 个人主页&#xff1a; 孙同学_ &#x1f527; 文章专栏&#xff1a;Liunx &#x1f4a1; 关注我&#xff0c;分享经验&#xff0c;助你少走弯路&#xff01; 文章目录 1. 前言2.关于gdb2.1 快速认识gdb2.2 安装cgdb2.3 gdb命令2.4 调试 & 断点 3.常见技巧3.…

ThinkPhp 5 安装阿里云内容安全(绿化)

composer require alibabacloud/green-20220302 首先要把php5(不支持php7)的执行文件设置到PATH环境变量 此外还要先执行composer update php5.5和php5.6的区别 5.5认为 <? 开头的也是php文件&#xff0c;包括 <?php 5.6认为 <? 开头的不是php文件&#xff0c;只…