概念
文件是被命名相关信息的集合体, 通常存放在外存(如磁盘、磁带)上, 可以作为一个独立单位存放和实施相应操作(如打开、关闭、读、写等)
linux中一切皆文件, 目录、设备(包括字符设备, 块设备)、进程、线程、套接字、管道都是文件
组成
目录项(文件名)
目录项使用户可通过文件名来访问文件系统中文件, 而无需直接知道文件物理存储位置
inode
inode文件索引节点, 包含与文件相关所有额外信息, 如文件类型、权限、硬链接数、所有者及所属组、文件大小、时间信息等
一个文件名只能与一个inode关联, 但一个inode可以关联多个文件名(通过硬链接)
inode与数据块之间是一一对应, 每个inode都指向一个或多个数据块, 数据块中存储文件具体内容
数据块
存放文件内容
linux中文件具体内容被分割成多个数据块存储在硬盘相应位置, 访问文件时系统会先通过inode找到数据块位置, 然后从数据块中读取内容
类型
linux支持多种类型文件, 每种文件类型都有其特定用途和特征
使用ls -la查看, 首字符代表文件类型
| 类型 | 首字符 |
|---|---|
| 普通文件 | - |
| 目录文件 | d |
| 字符设备文件 | c |
| 块设备文件 | b |
| 套接字文件 | s |
| 管道文件 | p |
| 链接文件 | l |
总计 400
drwxr-x---+ 27 dmjcb dmjcb 4096 Sep 2 4 14:08 .
drwxr-xr-x 3 root root 4096 Sep 1 27 23:07 ..
drwxrwxr-x 3 dmjcb dmjcb 4096 Sep 1 29 23:40 Arduino
drwxrwxr-x 2 dmjcb dmjcb 4096 Sep 1 29 23:40 .arduino15
-rw------- 1 dmjcb dmjcb 6437 Sep 1 30 01:19 .bash_history
-rw-r--r-- 1 dmjcb dmjcb 220 Sep 3 31 2024 .bash_logout
......
- 示例, 链接文件信息
ls -la /lib/x86_64-linux-gnu/libpcre2-16.so.0
lrwxrwxrwx 1 root root 21 Dec 10 2 2024 /lib/x86_64-linux-gnu/libpcre2-16.so.0 -> libpcre2-16.so.0.11.2
(1) lrwxrwxrwx 文件权限和类型
第一个字符l表示这是一个符号链接(symbolic link), 而不是一个普通文件或目录
接下来九个字符分为三组, 每组三个字符, 分别代表文件所有者的权限(rwx, 即读、写、执行)、所属组的权限(rwx, 同上)和其他用户的权限(rwx, 同上)
(2) 1 链接数
(3) root root 分别表示文件的所有者和所属组
(4) 21 文件大小, 单位是字节
对于符号链接来说表示链接文本(即目标路径)长度
(5) /lib/x86_64-linux-gnu/libpcre2-16.so.0 文件路径和名称
(6) -> libpcre2-16.so.0.11.2 链接指向目标, /lib/x86_64-linux-gnu/libpcre.so.3是一个指向libpcre2-16.so.0.11.2符号链接
当系统或程序尝试访问libpcre2-16.so.0 时, 实际上会访问到libpcre2-16.so.0.11.2
普通文件(regular file)
普通文件是最常见文件类型, 可以包含任何类型数据, 如文本、图像、音频, 有三种类型
- 纯文本文件(ASCII)
内容可以直接读取数据, 如数字、字母等
- 二进制文件(binary)
系统认识且可以执行, 例如可执行程序
- 数据格式文件(data)
特定格式文件, 某些程序运行时读取
目录文件(directory)
目录文件用于存储和管理其他文件和目录, 类似Windows中目录, 包含一个或多个文件和子目录列表
以./开头表示当前目录, ../表示上一级目录
链接文件(link)
链接文件指向另一个文件位置, 有三种类型
- 硬链接(hard link)
独立文件, 与被链接文件共享相同inode节点
- 软链接(soft link)
包含被链接文件路径信息, 只能在同一文件系统中使用
- 符号链接(symbolic link)
包含被链接文件路径信息, 可以跨文件系统使用, 相当于Windows快捷方式
设备文件(device file)
设备文件用于表示linux中设备, 如硬盘、鼠标、键盘等, 有两种类型
- 字符设备文件(character device file)
用于表示字符设备, 如打印机、鼠标等, 只能顺序访问, 不支持随机访问, 分为独占和共享两种,
独占字符设备只能由一个进程使用, 共享字符设备可以被多个进程共享
- 块设备文件(block device file)
用于表示块设备, 如硬盘、U盘等, 支持以block为单位进行随机访问, 分为固定大小和可变大小两种,
固定大小块设备文件大小固定, 不能更改;可变大小块设备文件大小可以动态调整
管道文件(Pipe)
管道文件用于实现进程间通信, 有两种类型
- 匿名管道(anonymous pipe)
用于父子进程之间通信
- 命名管道(named pipe)/FIFO(first in first out)管道
可在任意两个进程之间建立连接, 用于实现进程间同步和异步通信
命名FIFO管道可以在任意两个进程之间建立连接, 非命名FIFO管道只能在创建它的进程及其子进程中使用
套接字文件(socket)
套接字文件用于实现网络通信, 有两种类型
- UNIX域套接字(unix domain socket)
主要用于同一台计算机上进程间通信
- 网络套接字(network socket)
用于不同计算机之间进程间通信
文件描述符
文件描述符fd(file descriptor)是内核为管理已被打开文件所创建的索引, 是一个非负整数
其用于指代被打开文件, 所有执行I/O操作(如读写操作)系统调用都是通过文件描述符完成
属性
种类
程序运行时, 系统会默认分配三个文件描述符, 在程序运行期间始终存在, 并可以被重定向或使用于各种I/O操作
- 标准输入(
stdin)
文件描述符为0, 通常对应键盘输入, 重定向中可以对应其他文件或数据流
- 标准输出(
stdout)
文件描述符为1, 通常对应屏幕输出, 重定向中可以对应文件或其他数据流
- 标准错误(
stderr)
文件描述符为2, 通常对应屏幕输出, 用于显示错误信息, 重定向时可以单独处理
作用
- 唯一标识
文件描述符在内核中用于唯一标识一个打开文件
每个进程都有一个文件描述符表, 记录该进程使用所有文件描述符及相关信息
- 访问文件
通过文件描述符, 应用程序可以使用系统调用来读取、写入、关闭文件等操作
- 管理资源
文件描述符还用于管理套接字、管道等I/O资源, 使得进程能够高效地进行网络通信和进程间通信
使用
- open/close函数
open打开一个文件并获取其文件描述符, close函数将释放文件描述符
- read/write函数
通过文件描述符向文件中读取/写入数据
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main() {
int fd;
fd = open("example.txt", O_RDONLY);
if(fd == -1){
perror("open");
return 1;
}
const char *text = "Hello, World!\n";
ssize_t bytes_written;
bytes_written = write(fd, text, strlen(text));
if(bytes_written == -1){
perror("write");
}
ssize_t bytes_read;
char buffer[1024];
while((bytes_read = read(fd, buffer, sizeof(buffer) - 1)) > 0){
buffer[bytes_read] = '\0';
printf("%s", buffer);
}
if(bytes_read == -1){
perror("read");
}
close(fd);
return 0;
}
文件描述符表
文件描述符表是内核为每个进程维护的一个数据结构, 位于进程控制块(PCB)中, 用于记录该进程当前已打开所有文件或资源(如套接字、管道等)文件描述符及其相关信息, 包括指向内核中文件对象指针、文件状态(如读写位置、权限等)以及文件描述符本身
创建
进程创建时, 操作系统会为该进程分配一个空文件描述符表, 并初始化标准输入、标准输出和标准错误文件描述符
使用
进程运行中, 每当进程打开文件或资源时, 操作系统都会在文件描述符表中创建一个新表项来存储该文件描述符及其相关信息, 进程通过文件描述符表来访问和操作这些文件或资源
销毁
进程终止时, 操作系统会销毁该进程文件描述符表, 并释放所有打开文件或资源, 包括关闭文件描述符、释放内存和文件系统等资源
重定向
重定向是指将某文件描述符内容重定向到另一个文件描述符中, 或者重定向到文件、设备中
输出重定向
将命令输出(stdout或stderr)重定向到文件或另一个数据流中
(1) 使用>将stdout重定向到文件, 若文件已存在则会被覆盖
(2) 使用>>将stdout追加到文件末尾
(3) 对于stderr, 可以使用2>或2>>进行类似重定向
- 示例, 将stdout重定向到文件
echo "666" > a.txt
# 或
echo "666" 1> a.txt
- 示例, 将标准错误重定向到文件
ls test_file 2> error.txt
尝试列出名为test_file文件, 若文件不存在会产生一个错误消息并被重定向到error.txt中, 而不显示在终端上
- 示例, 通过输出重定向丢弃信息
#!/bin/bash
for i in {1..254};do
ip="192.168.3.${i}"
# 将标准/错误输出全部重定向到/dev/null中(丢弃产生所有信息)
ping -c 2 ${ip} > /dev/null &
done
输入重定向
使用<将文件内容作为命令输入
- 示例, 从文件读取输入
wc < input.txt
从input.txt文件中读取内容, 并使用wc命令(通常用于统计字数)进行处理
权限
linux文件权限控制用户对文件或目录访问和操作
类型
| 权限 | 含义 | 符号 | 数字值 |
|---|---|---|---|
| 可读 | 允许查看文件与目录列表 | r (read) |
4 |
| 可写 | 允许修改与在目录中新建、删除、移动文件或子目录 | w (write) |
2 |
| 可执行 | 允许运行程序, 切换目录 | x (execute) |
1 |
| 无权限 | 没有权限 | - |
0 |
读权限(r)
用户具有读权限可以查看文件内容, 可以列出目录中文件和子目录
写权限(w)
用户具有写权限可以修改文件内容, 可以在目录中创建、删除或重命名文件和子目录
执行权限(x)
用户具有执行权限可将文件作为程序运行, 可以进入目录
权限分组
linux系统中每个文件或目录都有三类权限, 分别针对所有者(Owner)、组成员(Group)和其他人(Others)设置
所有者(owner)
文件所有者, 通常是文件创建者
所有者对文件拥有最高权限, 可以执行所有类型操作(读、写、执行)
组成员(group)
文件所属组, 组内所有用户共享权限
组成员权限由文件所有者设置, 通常包括读权限和执行权限, 但不一定包括写权限
其他用户(others)
既不是文件所有者, 也不属于文件所属组用户
其他用户权限由文件所有者设置, 通常是最受限制
表现形式
stat .bashrc
File: .bashrc
Size: 3872 Blocks: 8 IO Block: 4096 regular file
Device: 259,2 Inode: 56229892 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ dmjcb) Gid: ( 1000/ dmjcb)
Access: 2026-02-03 16:38:09.136485970 +0800
Modify: 2026-01-27 23:40:30.118701235 +0800
Change: 2026-01-27 23:40:30.118701235 +0800
Birth: 2026-01-27 23:07:45.689791725 +0800
Access后9个字符每3个为一组, 每组依次代表文件所有者(属主)权限、同组所有者(属组)权限、其他用户权限
每组内部三个字符依次代表读、写、执行权限
- 示例, boot目录文件属性
drwxr-xr-x 4 root root 4096 Dec 13 18:09 boot
首字符d表示是目录文件
第一组rwx表示文件所有者拥有可读, 可写, 可执行权限
第二组r-x表示所有者同组用户拥有可读, 不可写, 可执行权限
第三组r-x表示其他用户拥有可读, 不可写, 可执行权限
命令
chmod
用于修改文件或目录权限
- 符号模式
由权限字符和操作符组成, 可以用来增加、删除或设置权限
chmod 符号 操作符 权限 文件/目录
| 符号 | 用户类型 | 权限范围 |
|---|---|---|
u |
user |
文件所有者(属主) |
g |
group |
文件所有者所在组(属组) |
o |
other |
所有其他用户 |
a |
all |
所用用户, 相当于 ugo |
| 操作符 | 含义 |
|---|---|
+ |
增加权限 |
- |
减去权限 |
= |
设置权限 |
示例, 给run.c所有者添加执行权限
chmod u+x run.c
- 绝对模式
是一个三位数数字, 其中每一位表示文件所有者、群组用户和其他用户权限
| 值 | 权限 | 含义 |
|---|---|---|
7 |
rwx |
读、写和执行权限 (4+2+1=7) |
6 |
rw- |
读和写权限 (4+2=6) |
5 |
r-x |
读和执行权限 (4+1=5) |
4 |
r-- |
只读权限 (4) |
3 |
-wx |
写和执行权限 (2+1=3) |
2 |
-w- |
只写权限 (2) |
1 |
--x |
只执行权限 (1) |
0 |
--- |
无权限 (0) |
chmod rwx(数字) 文件/目录
示例, 给a.txt添加全部权限
chmod 777 a.txt
示例, 权限设置为所有者具有读、写和执行权限, 文件所属组和其他用户具有读和执行权限
chmod 755 file
chown
用于修改文件或目录所有者
chown (选项) 所有者 文件/目录
- 示例, 将文件file.txt所有者修改为user
chown user file.txt
文件工具
awk
逐行读入文件, 以空格为默认分隔符将每行切片, 并进行各种分析处理
awk 'pattern { action }' 文件名
| 参数 | 含义 |
|---|---|
pattern |
指定要匹配模式 |
action |
匹配到内容时执行命令 |
| 内置变量 | 含义 |
|---|---|
NR |
当前记录数(行号) |
NF |
当前记录中字段数 |
$0 |
当前记录(整行) |
$1, $2.. |
当前记录字段 |
- 示例, 打印行号和每行内容
awk '{ print NR, $0 }' filename
- 示例, 打印文件第一列
awk '{ print $1 }' filename
BEGIN 和 END 块
BEGIN 块在处理任何输入行之前执行, END 块在处理完所有输入行之后执行
awk 'BEGIN { print "Start" } { print $1 } END { print "End" }' filename
grep
用于搜索文本中匹配指定模式字符串
grep 参数 匹配项 (文件名, 若为空则从标准输入读取)
graph LR;
F(参数)
F-->c("-c")-->c1(只输出匹配行数)
F-->i("-i")-->i1(忽略大小写)
F-->h("-h")-->h1(查询多文件时不显示文件名)
F-->l("-l")-->l1(查询多文件时只输出包含匹配字符文件名)
F-->n("-n")-->n1(显示匹配行及行号)
F-->s("-s")-->s1(不显示不存在或无匹配文本错误信息)
F-->v("-v")-->v1(显示不包含匹配文本的所有行)
F-->w("-w")-->w1(只匹配整个单词)
F-->x("-x")-->x1(只匹配整行)
单查询
- 模糊匹配
含有匹配项字段都会匹配
grep (模式) 匹配项
示例, 模糊匹配”abc”
# 匹配结果为abc abcd abcdef
grep "abc"
- 精确匹配
grep -w 匹配项
示例, 精确匹配”abc”
# 结果为abc
grep -w "abc"
与查询
在前一个查询结果中继续查询
grep '模式1' 匹配项 | grep '模式2'
- 示例, 查询3月10日16点30时间段内ssh登录成功情况
grep 'Mar 10 16:3' /var/log/secure | grep Accepted
或查询
grep '模式1|模式2' 匹配项
# 或者
grep -E '模式1|模式2' 匹配项
非查询
去除包含模式1进程行, 避免影响最终数据正确性
grep -v 模式1 匹配项
- 示例, 查询vlc进程信息时排除grep本身影响
ps -aux | grep vlc | grep -v grep
dmjcb 44028 1.0 0.3 1207748 109132 ? Sl 14:17 0:00 /usr/bin/vlc --started-from-file
如果不使用grep, 则会输出
dmjcb 44028 0.5 0.3 1207748 109132 ? Sl 14:17 0:00 /usr/bin/vlc --started-from-file
dmjcb 44171 0.0 0.0 9440 2408 pts/0 S+ 14:18 0:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox --exclude-dir=.venv --exclude-dir=venv vlc
正则
查看以pattern开头行
grep ^pattern
查找以pattern结尾行
grep pattern$
- 示例, 查找text.txt文件中含有human句子
grep human text.txt
- 示例, 查找text.txt文件中以The开头句子
grep ^The text.txt
sed
对文本进行过滤和转换
sed 参数 '起始范围, 结束范围 操作' 文件
graph LR;
S(sed)
S-->C(操作)
S-->P(参数)
S-->D(范围)
P-->n("-n")-->n1(忽略执行过程的输出只输出结果)
P-->i("-i")-->i1(改动将覆盖原文件, 可用-i.bak备份)
D-->x(x)-->x1(选择第x行, 若为空选择全部行)
D-->y(x,y/x, +y)-->y1(选择x到y行, 共y - x + 1行)
D-->z(1~2)-->z1(选择偶数行)
D-->a(2~2)-->a1(选择偶数行)
D-->b(x, $)-->b1(从第x行到文件结尾)
C-->p(p)-->p1(打印匹配内容)
C-->d(d)-->d1(删除匹配内容, 此时要去掉-n参数)
C-->w(w)-->w1(将匹配内容写入其他地方)
C-->g(g)-->g1(全部替换)
替换
sed s#旧文本#新文本#flags
graph LR;
F(flags)
F-->G(g)-->G1(全局替换)
F-->P(p)-->P1(打印替换结果)
F-->W(w 文件)-->W1(将替换结果写入文件)
- 示例, 将file.txt中foo替换为bar
sed 's#foo#bar#' file.txt
- 示例, ubuntu换源
sed -i 's#security.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list
sed -i 's#cn.archive.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list
打印
若字符串中带有路径符号 /, 可用 # 分隔
- 示例, 打印file.txt 1-5行
sed -n '1, 5 p' file.txt
添加
- 末前添加
sed -i '1i内容' 路径
- 末行行前添加
sed -i '$i内容' 路径
- 末行后添加
sed -i '$a内容' 路径
xargs
管道符 | 是将前个命令标准输出作为后个命令标准输入
xargs 将前命令标准输出作为后命令参数, 可单独使用, 也可与管道符、重定位符等与其他命令配合使用
默认动作是echo, 默认分隔符为空白字符(空格, TAB, 换行符)
真正执行命令在xargs后面, 接受xargs传参
xargs 命令
- 示例, 根据VLC进程ID结束进程
ps -aux | grep vlc | grep -v grep | awk '{print $2}' | sudo xargs kill -9
文件命令
内容
追加
追加单行
echo 内容 >> 文件路径
- 示例, main.txt单行多行追加
echo "aaaaaaa" >> main.txt
追加多行
sudo bash -c cat >> 文件路径 << EOF
....
EOF
- 示例, 多行追加
sudo bash -c cat >> main.txt << EOF
> 1
> 2
> 3
> EOF
覆盖
echo 内容 > 文件路径
复制
cp (选项) 源文件 目标文件
graph LR;
P(选项)
P-->A("-a/--archive")-->A1(归档复制, 保留链接、文件属性)
P-->B("-r/--recursive")-->B1(递归复制目录及其内容)
P-->C("-u/--update")-->C1(仅在源文件比目标文件新或目标文件不存在时复制)
- 复制单个文件
cp 文件源路径 文件目标路径
- 复制目录
cp -r 目录源路径 目录目标路径
搜索
find 起始目录 搜索条件 (操作)
graph LR;
P(参数)
P-->A(起始目录)-->A1(指定搜索起始位置, 若省略默认为当前目录)
P-->B(搜索条件)
B-->B1("-name")-->B11(按文件名搜索)
B-->B2("-type")-->B21(按文件类型搜索, f表示文件, d表示目录)
B-->B3("-size")-->B31(按文件大小搜索, 例如 +100M 表示大于100MB文件)
B-->B4("-atime")-->B41(按文件访问时间搜索, 例如+100 表示100天)
P-->C(操作)-->C1(对找到文件执行操作)
- 示例, 在/home/dmjcb 中搜索.bin结尾文件
find $HOME$ -name *.bin
输出
/home/dmjcb/.cache/ibus/libpinyin/user_pinyin_index.bin
/home/dmjcb/.cache/ibus/libpinyin/user.bin
/home/dmjcb/.cache/ibus/libpinyin/addon.bin
/home/dmjcb/.cache/ibus/libpinyin/user_phrase_index.bin
/home/dmjcb/.cache/ibus/libpinyin/network.bin
- 示例, 搜索在过去100天内未被使用过执行文件
find /usr/bin -type f -atime +100
tar
打包是将众多文件或目录变成一个总文件, 压缩是将大文件通过压缩算法变成小文件
tar(tape archive)打包工具可以将多个文件和目录打包成一个文件, 也可压缩
打包
tar -cvf *.tar 源目录
-c 表示创建新归档文件, -v 表示显示详细信息,-f 后面跟归档文件名
压缩
- 打包并压缩为gzip
tar -czvf *.tar 源目录
-z表示使用gzip压缩
解压
- 解压 .tar
tar -xvf archive_name.tar
- 解压 .tar.gz 或 .tgz
tar -xzvf archive_name.tar.gz
链接
| 软链接 | 硬链接 |
|---|---|
| 以路径形式存在(快捷方式) | 以文件副本形式存在, 不占实际空间 |
| 可对目录进行链接 | 不可给目录创建链接 |
| 可跨文件系统 | 不可跨文件系统 |
软链接
ln -s 源文件 链接文件
硬链接
ln 源文件 链接文件