6.1 目录与路径
6.1.1 相对/绝对路径的选择原则
| 场景 | 用哪种 | 原因 |
|---|---|---|
| 写 shell script | 绝对路径 | 无论在哪执行都不出错 |
| 日常操作 | 相对路径 | 打字少;软件在不同机器上安装路径不同时也能用 |
| 工作调度(cron/at) | 绝对路径 | 执行环境不固定,相对路径会跑偏 |
6.1.2 目录操作指令
特殊目录符号:
| 符号 | 含义 |
|---|---|
. | 当前目录 |
.. | 上一层目录 |
- | 前一个工作目录(cd - 切回去) |
~ | 当前用户主文件夹 |
~account | account 这个用户的主文件夹 |
💡 根目录
/的..就是/自己——ls -al /可以看到.和..权限属性完全一致。
四个目录操作指令:
| 指令 | 用途 | 关键参数 |
|---|---|---|
cd | 变换目录 | cd ~ / cd 回家;cd - 回上一个;cd .. 回上层 |
pwd | 显示当前目录 | -P:显示真实路径而非链接路径 |
mkdir | 创建目录 | -p:递归创建多层;-m 711:直接指定权限 |
rmdir | 删除空目录 | -p:连上层空目录一起删 |
pwd -P 的实际用途:/var/mail 是个符号链接指向 /var/spool/mail,普通 pwd 显示 /var/mail,加 -P 才显示真实物理路径。
6.1.3 环境变量 $PATH——为什么任何地方都能执行 ls
echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin系统按 PATH 中目录的顺序搜寻同名可执行文件,找到第一个就执行。
五个核心认知:
- 不同身份默认 PATH 不同(root 有
/sbin系列,普通用户没有) - PATH 可以修改:
PATH="${PATH}:/root" - 用绝对/相对路径执行比靠 PATH 更准确
- 指令应该放到正确目录下
.(本目录)绝不应该加入 PATH——安全风险:坏人在/tmp放一个叫ls的木马,root 进了 /tmp 执行 ls 就中招
6.2 文件与目录管理
6.2.1 ls 的常用选项
前面章节已经用过很多,这里集中列出最有用的:
| 选项 | 用途 | 场景 |
|---|---|---|
-l | 长格式(权限/拥有者/时间…) | 最常用,ll = ls -l |
-a | 含隐藏文件 | 看配置 |
-d | 只看目录本身不看内容 | 检查目录权限 |
-h | 人类可读大小(KB/MB/GB) | 配合 -l |
-i | 显示 inode 号码 | 第七章会用 |
-R | 递归列出子目录 | 看整个目录树 |
-S | 按大小排序 | 谁在吃磁盘 |
-t | 按时间排序 | 最近改了什么 |
-r | 反向排序 | 配合 -t 看最旧文件 |
--full-time | 完整年月日时分 | 只看年份不够时 |
-F | 文件名后加后缀标记(`*/=>@ | `) |
--time=atime/ctime | 看 access 或 status 时间 | 排查问题 |
6.2.2 复制/删除/移动:cp, rm, mv
cp(复制) 的核心行为:
- 默认 cp 后拥有者变成操作者自己,时间也更新
- 备份用
-a(=-dr --preserve=all):完整保留权限/拥有者/时间 - 复制目录加
-r,但用-a更好(属性不会变) -i:覆盖前询问;-u:目标文件更旧才覆盖(增量备份)-s:创建符号链接(捷径),-l:创建硬链接(下一章讲)-d:复制链接文件本身而非它指向的真实文件
cp ~/.bashrc /tmp/bashrc # 简单复制,拥有者变成 root
cp -a /var/log/wtmp /tmp/ # 完整备份,属性一丝不变
cp -r /etc/ /tmp/ # 递回复制整个目录
cp -s bashrc bashrc_slink # 创建符号链接
cp -u ~/.bashrc /tmp/bashrc # 来源更新时才覆盖💡 复制别人的文件想送给第三方:cp 后拥有者还是自己,需要再
chown给对方,否则对方改不了。
rm(删除)——最危险的指令:
rm -i file # 询问后删除(CentOS 默认 root 加了 -i)
rm -r /tmp/etc/ # 递回删除目录(非常危险!)
\rm -r /tmp/etc # 前面加 \ 跳过 alias,不询问直接删!
rm ./-aaa- # 删除以 - 开头的文件,必须前面加 ./rmdir只能删空目录,安全但不实用rm -rf /是著名的自毁指令,绝对不要试- 文件名以
-开头时,必须用./-filename或rm -- -filename
mv(移动/更名)——同一文件系统内只是改目录条目,几乎瞬间完成:
mv bashrc mvtest/ # 移动到目录
mv mvtest mvtest2 # 更名!(Linux 没有 rename 指令做单文件改名)
mv f1 f2 f3 dir/ # 多个文件移到同一目录6.2.3 basename 与 dirname
basename /etc/sysconfig/network # → network
dirname /etc/sysconfig/network # → /etc/sysconfig主要用于 shell script 中提取路径的各个部分。
6.3 文件内容查阅
6.3.1 一次性显示:cat / tac / nl
| 指令 | 功能 | 关键选项 |
|---|---|---|
cat | 从第一行开始输出 | -n 含空白行加行号;-b 空白行不加行号;-A 显示所有隐藏字符($=换行, ^I=Tab) |
tac | 从最后一行开始输出 | cat 倒过来写 |
nl | 加行号输出 | -b a 空白也编号;-n rz 行号前面补 0;-w 3 行号占 3 位 |
6.3.2 翻页查看:more / less
| 功能 | more | less(更好用) |
|---|---|---|
| 向下翻页 | 空格 | 空格 / PageDown |
| 向上翻页 | 不支持 | PageUp / b |
| 向下搜索 | /关键词 | /关键词 |
| 向上搜索 | 不支持 | ?关键词 |
| 跳到第一行 | 不支持 | g |
| 跳到最后一行 | 不支持 | G |
| 退出 | q | q |
💡
man page的浏览界面就是调用的less——所以学 less 等于学 man 的操作。
6.3.3 数据撷取:head / tail
head -n 20 file # 前 20 行(默认 10 行)
head -n -100 file # 除了最后 100 行,其余全输出
tail -n 20 file # 最后 20 行
tail -n +100 file # 从第 100 行开始到末尾
tail -f /var/log/messages # 持续监控,新内容实时显示(Ctrl+C 停止)经典组合——取第 11~20 行:
head -n 20 file | tail -n 10 # 先拿前 20 行,再取后 10 行
cat -n file | head -n 20 | tail -n 10 # 顺便带行号| 是管线(pipe):前面指令的输出交给后面指令继续处理,而不是输出到屏幕。
6.3.4 读二进制文件:od
od -t c /usr/bin/passwd # 以 ASCII 字符显示二进制内容
od -t oCc /etc/issue # 同时显示八进制数值和 ASCII 字符
echo password | od -t oCc # 查 "password" 每个字母的 ASCII 码最左边一列是八进制的字节偏移量(0000020 = 第 16 个 byte = 2×8)。
6.3.5 修改时间或创建空文件:touch
Linux 文件有三个时间:
| 时间 | 全称 | 何时更新 |
|---|---|---|
| mtime | modification time | 文件内容被修改(ls -l 默认显示的) |
| ctime | status time | 文件状态被改变(权限、拥有者变更) |
| atime | access time | 文件内容被读取(cat 也会更新它) |
touch file # 文件存在→三个时间全更新为现在;不存在→创建空文件
touch -d "2 days ago" file # 修改 mtime 和 atime,但不改 ctime
touch -t 201406150202 file # 精确设置到 YYYYMMDDhhmm💡
cp -a可以复制 mtime 和 atime,但 ctime 永远无法复制——因为”复制”这个动作本身就是一次状态变更。
6.4 文件默认权限与隐藏权限
6.4.1 umask——新建文件/目录的默认权限
umask 是指”默认要拿掉的权限”,不是默认权限本身。
| 文件 | 目录 | |
|---|---|---|
| 最大默认 | -rw-rw-rw-(666,文件天生没有 x) | drwxrwxrwx(777) |
| root 的 umask=022 | 666 - 022 = 644(rw-r—r—) | 777 - 022 = 755(rwxr-xr-x) |
| 普通用户 umask=002 | 666 - 002 = 664(rw-rw-r—) | 777 - 002 = 775(rwxrwxr-x) |
umask # 查看数字 → 0022(只看后三位 022)
umask -S # 查看符号 → u=rwx,g=rx,o=rx
umask 002 # 修改为 002(同群组也能写)💡 用减法算 umask 是错误的:666-003=663 但实际是
-rw-rw-r--(664)。因为 x 在文件上是直接被 umask 拿掉的,不能”加回来”。正确理解是”默认值减去 umask 中每个位置上对应的权限位”。
umask 的团队协作意义:如果团队共用目录,umask 002 让群组成员可以互相编辑对方新建的文件;umask 022 则只有创建者自己能写。
6.4.2 文件隐藏属性:chattr / lsattr
仅在 Ext2/Ext3/Ext4 下完整生效,xfs 只部分支持。
| 属性 | 效果 | 使用场景 |
|---|---|---|
+i | 文件完全不可变:不能删/改名/修改/写(root 也不行!) | 保护关键配置不被误改 |
+a | 只能追加数据,不能删/改已有内容 | 日志文件防篡改 |
+A | 不更新 atime | 减少磁盘 I/O |
+S | 同步写入硬盘 | 数据安全 |
chattr +i /etc/shadow # 连 root 都删不掉
chattr -i /etc/shadow # 解除
lsattr /etc/shadow # 查看隐藏属性 → ----i-----------6.4.3 特殊权限:SUID / SGID / SBIT
ls -l /usr/bin/passwd → -rw**s**r-xr-x(注意那个 s)
ls -ld /tmp → drwxrwxrw**t**(注意那个 t)
| 权限 | 位置 | 数字 | 作用对象 | 效果 |
|---|---|---|---|---|
| SUID | owner 的 x 位→s | 4 | 二进制程序 | 执行时获得文件拥有者的权限 |
| SGID | group 的 x 位→s | 2 | 二进制程序/目录 | 执行时获得文件所属群组的权限;目录下新建文件的群组继承目录群组 |
| SBIT | others 的 x 位→t | 1 | 目录 | 只有创建者和 root 才能删除自己的文件 |
SUID 的经典案例——为什么普通用户能改自己的密码:
/usr/bin/passwd有 SUID,拥有者是 root- dmtsai 执行 passwd 时,暂时获得 root 权限
- 所以能写
/etc/shadow(权限 000,只有 root 能改) - 但 dmtsai 直接
cat /etc/shadow就不行——cat 没有 SUID
SGID 对目录的团队协作价值:设了 SGID 的目录,任何人在里面新建的文件,群组都跟着目录走,而不是创建者的默认群组——完美解决多人共享目录的权限问题。
SBIT 的典型应用——/tmp:任何人都能创建文件,但只能删自己的。
设置方法(在前面加第四位数字):
chmod 4755 file # SUID → -rwsr-xr-x
chmod 2755 dir # SGID → drwxr-sr-x
chmod 1755 dir # SBIT → drwxr-xr-t
chmod 7666 file # 空的 SUID/SGID/SBIT → -rwSrwSrwT(大写表示底下没 x)💡 大小写 S/T 的含义:
s/t= x 权限 + 特殊权限;S/T= 该位原本就没有 x,特殊权限是”空”的——文件拥有者自己都执行不了,哪来的权限借给别人?
符号法:u+s(SUID)、g+s(SGID)、o+t(SBIT)。
6.4.4 file——判断文件类型
file ~/.bashrc # → ASCII text
file /usr/bin/passwd # → setuid ELF 64-bit LSB shared object ...
file /var/lib/mlocate/mlocate.db # → data6.5 指令与文件的搜寻
搜寻优先级:which/type(查指令) → whereis(查特定目录) → locate(查数据库) → find(全盘搜索,最慢最后用)
6.5.1 找指令:which / type
which ifconfig # /sbin/ifconfig
which -a which # 列出所有同名可执行文件
which history # 找不到!因为 history 是 bash 内置指令,不在 PATH 目录里type 能区分内置指令和外部指令(后面 bash 章节会讲)。
6.5.2 找文件:whereis / locate / find
| 指令 | 速度 | 原理 | 限制 |
|---|---|---|---|
| whereis | 极快 | 只搜几个特定目录(/bin, /sbin, /usr/share/man…) | 搜不到不在这几个目录里的文件 |
| locate | 很快 | 查数据库 /var/lib/mlocate/mlocate.db | 新文件还没入数据库时搜不到,要先 updatedb |
| find | 慢 | 直接扫硬盘 | 最强大,什么都能找 |
locate:
locate -l 5 passwd # 只显示前 5 条结果
locate -S # 查看数据库统计信息
updatedb # 手动更新数据库(读硬盘,要几分钟)find——王牌指令,按条件搜:
# 按时间
find / -mtime 0 # 24小时内修改过的文件
find /var -mtime -4 # 4天内修改过的
find /var -mtime +4 # 4天前修改过的(不含4天本身)
find /etc -newer /etc/passwd # 比 passwd 更新的文件
# 按使用者
find /home -user dmtsai # 属于 dmtsai 的所有文件
find / -nouser # 拥有者不存在于 /etc/passwd 的"无主"文件
# 按名称/大小/类型
find / -name "*.conf" # 文件名匹配
find / -size +50k # 大于 50KB 的文件
find / -type f # 只找正规文件(d=目录, l=链接)💡
-mtime n的 “n” 含义:(见书图 6.5.1)-mtime 4= 距今 45 天前那 24 小时内;4 天内;-mtime -4= 距今 0-mtime +4= 距今 5 天前及更早。
关键命令
| 命令 | 用途 | 最常用选项 |
|---|---|---|
cd | 变换目录 | cd ~, cd -, cd .. |
pwd -P | 显示当前真实路径 | -P 显示物理路径非链接路径 |
mkdir -p | 创建目录 | -p 递归;-m 711 设权限 |
rmdir -p | 删除空目录 | -p 连上层空目录一起删 |
ls -al | 列出文件属性 | -l 长格式;-a 含隐藏;-h 人类可读 |
cp -a | 复制(完整保留属性) | -a 全保留;-r 递回;-i 询问;-u 增量 |
rm -rf | 删除(极其危险) | -r 递回;-f 强制;-i 询问 |
mv | 移动/更名 | -u 更新;-i 询问覆盖 |
basename | 取文件名 | basename /a/b/c → c |
dirname | 取目录名 | dirname /a/b/c → /a/b |
cat -n | 显示文件内容 | -n 行号;-A 显示隐藏字符 |
tac | 反向显示 | 最后一行先出 |
nl | 加行号输出 | -b a 全编号;-n rz 补 0 |
more / less | 翻页查看 | less 可前后翻+搜索 |
head -n N | 取前 N 行 | -n -100 跳过最后 100 行 |
tail -n N / tail -f | 取后 N 行 / 实时监控 | -f 实时跟踪日志 |
od -t c | 读二进制文件 | -t oCc 八进制+ASCII 对照 |
touch | 创建空文件/更新时间戳 | -d "2 days ago";-t YYYYMMDDhhmm |
umask | 查看/设默认权限 | umask 002;umask -S |
chattr +i / lsattr | 设置/查看隐藏属性 | +i 不可变;+a 只可追加 |
chmod 4755 | 设 SUID | 4=SUID, 2=SGID, 1=SBIT |
file | 判断文件类型 | 区分 ASCII/binary/data |
which | 找可执行文件路径 | -a 列出所有 |
whereis | 找特定目录下文件 | -b 只找 binary;-m 只找 man |
locate | 数据库搜文件名 | -i 忽略大小写;先 updatedb |
find | 全盘条件搜索 | -mtime, -user, -name, -size, -type |