
个人主页:
wengqidaifeng
✨ 永远在路上,永远向前走
个人专栏:
数据结构
C语言
嵌入式小白启动!
重要OJ算法题详解
蓝桥杯备战
C++从菜鸟到强手
Linux操作系统的奇妙之旅
python启航
AI大模型Agent:拥抱未来,赋能自己
26电赛H题:车载小球平衡系统
文章目录
- [从"会敲命令"到理解 Linux:15 个基础指令、文件树与命令执行的本质](#从“会敲命令”到理解 Linux:15 个基础指令、文件树与命令执行的本质)
-
- [一、为什么学 Linux 要先学"黑屏终端"](#一、为什么学 Linux 要先学“黑屏终端”)
- 二、先建立正确的文件系统地图
- [三、15 个命令:围绕"位置、对象、内容、帮助"来学习](#三、15 个命令:围绕“位置、对象、内容、帮助”来学习)
-
- [1. `pwd`:我现在在哪里](#1.
pwd:我现在在哪里) - [2. `cd`:改变 Shell 的工作目录](#2.
cd:改变 Shell 的工作目录) - [3. `ls`:查看目录项和文件属性](#3.
ls:查看目录项和文件属性) - [4. `touch`:创建空文件,或更新时间戳](#4.
touch:创建空文件,或更新时间戳) - [5. `stat`:把文件属性看清楚](#5.
stat:把文件属性看清楚) - [6. `mkdir`:创建目录](#6.
mkdir:创建目录) - [7. `tree`:把目录层次画出来](#7.
tree:把目录层次画出来) - [8. `rmdir`:只删除空目录](#8.
rmdir:只删除空目录) - [9. `rm`:删除目录项,务必理解风险](#9.
rm:删除目录项,务必理解风险) - [10. `cp`:复制内容,源对象仍保留](#10.
cp:复制内容,源对象仍保留) - [11. `mv`:移动或重命名](#11.
mv:移动或重命名) - [12. `cat`:连接并输出文件内容](#12.
cat:连接并输出文件内容) - [13. `man`:向系统手册提问](#13.
man:向系统手册提问) - [14. `which`:查看 PATH 中会找到的可执行程序](#14.
which:查看 PATH 中会找到的可执行程序) - [15. `alias`:给常用命令定义别名](#15.
alias:给常用命令定义别名)
- [1. `pwd`:我现在在哪里](#1.
- 四、命令的本质:可执行文件,但不止可执行文件
- 五、通配符为什么既高效又危险
- 六、用一个小实验串联全部知识
- [七、结语:真正要记住的不是 15 个单词](#七、结语:真正要记住的不是 15 个单词)
从"会敲命令"到理解 Linux:15 个基础指令、文件树与命令执行的本质
面向第一次接触 Linux 命令行的学习者。本文不追求堆砌参数,而是用一条主线把
pwd、cd、ls、touch、stat、mkdir、tree、rmdir、rm、cp、mv、cat、man、which、alias等常用命令串起来:我们在终端中做的事情,本质上是在让 Shell 解析文字、定位程序,再请求内核操作文件和进程。

一、为什么学 Linux 要先学"黑屏终端"
Windows 和桌面版 Linux 都有图形界面。双击文件夹、拖动文件、点击删除,看起来与终端毫无关系,但图形界面并不是另一套计算机规律。文件管理器收到鼠标事件后,仍然要调用操作系统提供的接口完成打开、复制、移动和删除。终端只是把"点击菜单"换成了"输入精确的文字"。
服务器往往不安装桌面环境。一方面,图形桌面会占用内存、磁盘和网络带宽;另一方面,服务器常被放在机房或云平台,我们通过 SSH 远程管理它。命令行还有三个图形界面难以替代的优势:可重复、可组合、可自动化。一条经过验证的命令可以写进脚本,在十台甚至一千台机器上执行;一个图形界面的拖拽过程却很难原样复现。
终端、Shell 和 Linux 内核不是同一个东西。终端负责显示字符和接收键盘输入;Shell(常见的是 Bash)读取并解释命令;内核管理进程、内存、设备和文件系统。看到提示符:
bash
root@server:~#
可以把它拆成"当前用户是 root、主机名是 server、当前目录用 ~ 表示、# 暗示这是超级用户"。普通用户的提示符通常是 $。提示符不是命令的一部分,复制示例时不要把 $ 或 # 一起输入。
一些基础交互同样重要:clear 清屏;方向键上、下翻阅历史命令;Tab 补全命令或文件名;Ctrl+C 向前台进程发送中断信号,常用于停止卡住或持续运行的程序;Ctrl+D 表示输入结束(EOF),在空提示符下通常会退出当前 Shell。不同终端的复制粘贴快捷键可能不同,XShell 常用 Ctrl+Insert 复制、Shift+Insert 粘贴。
二、先建立正确的文件系统地图
Windows 路径常见 C:\Users\name,Linux 使用正斜杠 /home/name。Linux 文件系统从唯一的根目录 / 开始,整体是一棵树。目录负责记录"名字到对象"的映射,普通文件保存内容与属性。严格来说,目录也是一种特殊文件,只是它的内容由文件系统按特定格式维护。

已把pwd、whoami、ls 和路径关系画在了一起。阅读时要抓住两个不同问题:whoami 回答"当前进程以哪个用户身份运行",pwd 回答"当前 Shell 的工作目录是什么"。身份影响权限,位置决定相对路径的参照点。

/home/bit/test.c 是绝对路径,因为它从根目录 / 开始;src/main.c 是相对路径,因为它要结合当前工作目录才能确定。绝对路径稳定,适合配置文件和脚本中的固定位置;相对路径短,适合日常操作,但执行前必须知道自己身在何处。
每个目录都有两个特殊名字:. 表示当前目录,.. 表示父目录。根目录的 .. 仍指向根目录本身。~ 则是 Shell 展开的家目录符号:普通用户 zhangsan 通常对应 /home/zhangsan,root 的家目录通常是 /root。注意,.、.. 是目录语义,~ 是 Shell 语法,它们不处于完全相同的层次。
路径为什么重要?因为"文件名"只需在同一目录中唯一,不同目录完全可以各有一个 test.c。真正定位对象的是路径。把文件系统理解成树以后,cd ..、cp ./a.txt ../backup/ 就不再是需要死记的咒语,而是沿树移动或指定源、目标。
从树的节点角度看,普通文件不能再包含子节点,因此一定是叶子节点;空目录也可以是叶子节点;非空目录则是中间节点。板书中的 /usr/bin、/usr/lib、/home/bit/test.c 正是在用这个模型说明:从根目录开始沿唯一分支向下,就能定位某个对象。

三、15 个命令:围绕"位置、对象、内容、帮助"来学习
1. pwd:我现在在哪里
pwd 是 print working directory 的缩写,用于打印当前 Shell 的工作目录:
bash
$ pwd
/home/bit/project
每个进程都有当前工作目录。Shell 也是进程,因此它会保存自己的工作目录;其后启动的程序通常继承这个位置。危险操作前先运行 pwd,不是仪式,而是在确认相对路径和通配符究竟会落到哪里。
与板书中的 whoami 配合使用,可以快速确认当前上下文:
bash
$ whoami
bit
$ pwd
/home/bit
root 登录后的家目录通常是 /root,普通用户 bit 的家目录通常是 /home/bit。但 whoami 的输出不会直接决定 pwd 的结果:用户可以 cd 到自己有权进入的其他目录,因此二者不能互相替代。
2. cd:改变 Shell 的工作目录
bash
cd / # 到根目录
cd ~ # 到当前用户家目录
cd .. # 到父目录
cd - # 回到上一次所在目录
cd ./src # 以当前目录为参照进入 src
cd 通常是 Shell 内建命令,而不是一个普通外部程序。原因很关键:如果让子进程改变目录,改变的只是子进程自己的工作目录,子进程退出后父 Shell 不会移动。只有 Shell 自己执行 cd,新的位置才能影响后续命令。
3. ls:查看目录项和文件属性
bash
ls # 当前目录中的非隐藏项
ls -l # 长格式
ls -a # 包括以 . 开头的隐藏项
ls -lah # 组合选项,并用易读单位显示大小
ls -ld / # 看目录 / 本身,而不是列出其内容
ls -l 第一列如 drwxr-xr-x:首字符 d 表示目录,- 表示普通文件,l 表示符号链接;后九位是所有者、所属组、其他人的读写执行权限。后面还能看到链接数、所有者、组、大小、时间和名称。所谓"隐藏文件"并没有神秘属性,只是名字以 . 开头,ls 默认不显示它。
板书特别区分了两个容易混淆的操作:
bash
ls -l /home/bit # 列出目录里面的内容
ls -ld /home/bit # 显示这个目录本身的属性
ls -lad / # 组合使用 -l、-a、-d
最后一条命令中,-d 才是"看目录本身"的关键;-a 在只显示 / 本身时通常没有额外效果。命令选项可分别写成 -l -a -d,也可在工具支持时合并成 -lad。
ll 常常只是发行版或用户配置中的别名,并非所有系统都存在。遇到 ll: command not found 时,用 ls -l 即可。
4. touch:创建空文件,或更新时间戳
bash
touch notes.txt
touch a.c b.c
若路径不存在,touch 创建一个空的普通文件;若文件已存在,它默认更新访问时间(atime)和内容修改时间(mtime)。文件状态改变会使 ctime 由内核更新。ctime 不是"创建时间",而是 inode 状态变化时间。许多 Linux 文件系统另有 birth time,但工具和文件系统是否展示它并不统一。
因此,"文件 = 内容 + 属性"是非常有用的模型。修改正文会改变内容和 mtime;修改权限不会改变正文,但会改变元数据和 ctime。
5. stat:把文件属性看清楚
bash
stat notes.txt
stat 会显示大小、块数、inode、权限、UID/GID 以及 Access、Modify、Change 等时间。Access 是读取相关时间,Modify 是文件内容最后修改时间,Change 是 inode 元数据最后改变时间。实际系统可能采用 relatime、noatime 等挂载策略,因此读取文件不一定每次都把 atime 写回磁盘。
6. mkdir:创建目录
bash
mkdir demo
mkdir -p project/src/include
mkdir 创建一个目录;-p 会把缺失的父目录一并创建,并在目录已存在时不把它当作错误。请注意语义:目录不是"装文件的普通文件",它是文件系统用来组织名称的特殊对象。
7. tree:把目录层次画出来
bash
tree project
tree -a project
tree 递归显示层次,比连续执行多次 ls 更直观。它不一定预装:Debian/Ubuntu 可用 sudo apt install tree,RHEL 系可用 sudo dnf install tree。安装软件会改变系统状态,学习时应先确认发行版及权限,不要看到命令就盲目以 root 执行。
8. rmdir:只删除空目录
bash
rmdir empty_dir
rmdir -p a/b/c
rmdir 默认只删除空目录,这个限制反而提供了一层保护。-p 会在删除末级后继续尝试删除已经变空的父目录;任何一级仍有内容就会停止。
9. rm:删除目录项,务必理解风险
bash
rm file.txt # 删除普通文件
rm -i file.txt # 删除前询问
rm -r old_dir # 递归删除目录树
rm -rf old_dir # 递归并忽略大多数提示与不存在错误
rm 通常不是把数据送进"回收站",而是请求文件系统解除目录项与 inode 的链接。没有其他硬链接且没有进程继续打开它时,对象才会在文件系统层面被回收。恢复并不可靠,所以不要把 -f 当作日常习惯。
通配符 * 也不是 rm 解析的,而是 Shell 在启动 rm 之前展开。例如目录里有 a.log、b.log,输入 rm *.log,Shell 实际交给程序的参数类似 rm a.log b.log。这解释了为什么安全预览有效:先执行 printf '%s\n' ./*.log 或 ls -- ./*.log,看到展开结果后再删除。
绝不要实验 rm -rf / 或 rm -rf /*。现代 GNU rm 对直接删除 / 有保护,但 /* 会先被 Shell 展开,仍可能造成灾难。比背诵"危险命令"更可靠的习惯是:不用 root 做日常工作;变量加引号;使用明确目录;先 pwd、再预览;需要时加 -i;备份重要数据。
10. cp:复制内容,源对象仍保留
bash
cp a.txt b.txt
cp a.txt backup/
cp -r project backup/
cp -a project backup/
目标是已有目录时,源会复制到目录内部;目标不存在且源是单文件时,目标会成为新文件名。复制目录需要递归选项。备份时常用 -a(archive),它递归复制并尽量保留链接、权限和时间等属性。覆盖重要文件前可用 -i 询问,或者先检查目标。
把板书中的写法统一成"源 → 目标"更容易判断:
| 命令 | 结果 |
|---|---|
cp src.txt dst.txt |
复制并命名为 dst.txt |
cp src.txt dir/ |
得到 dir/src.txt |
cp src.txt dir/new.txt |
得到 dir/new.txt |
cp -r srcdir dstdir |
递归复制目录,具体层次取决于目标是否已存在 |
cp -rf 中 -r 表示递归,-f 表示必要时强制处理目标,但它不会让错误路径变正确。日常学习不应默认携带 -f,先用 ls -ld -- 源 目标 检查两端类型更可靠。
11. mv:移动或重命名
bash
mv old.txt new.txt
mv report.txt archive/
mv -i a.txt archive/a.txt
目标是目录时表示移动进去;目标是一个新名字时表示重命名。同一文件系统内的移动常常只需修改目录项,因此很快;跨文件系统移动通常退化为"复制后删除",成本和风险都会提高。这也是理解命令表面相同、底层行为可能不同的好例子。
12. cat:连接并输出文件内容
bash
cat README.md
cat part1 part2 > all.txt
cat -n source.c
cat 名称来自 concatenate(连接)。它适合短文本或把多个输入顺序送到标准输出,不适合直接浏览几万行日志,因为内容会快速刷屏。长文件使用 less;只看开头用 head;追踪日志尾部用 tail -f。
这里的 > 是 Shell 的输出重定向,不是 cat 的选项。Shell 先打开或截断 all.txt,再让 cat 的标准输出指向它。>> 则是追加。理解"标准输入、标准输出、标准错误"后,命令才能真正组合起来。
13. man:向系统手册提问
bash
man ls
man 1 printf # 第 1 章:用户命令
man 2 open # 第 2 章:系统调用
man 3 printf # 第 3 章:库函数
不必记住每个参数,应该学会查手册。进入 man 后用 /关键词 搜索,n 跳到下一个匹配,q 退出。man printf 可能优先显示命令,而 C 语言库函数应明确写 man 3 printf。如果系统没有手册,需要按发行版安装 man pages。
14. which:查看 PATH 中会找到的可执行程序
bash
which ls
which gcc
which 通常沿 PATH 查找命令对应的可执行文件,例如 /usr/bin/ls。但别名、Shell 函数、内建命令不一定能由 which 准确解释。Bash 中更可靠的综合检查是:
bash
type -a cd
type -a ls
command -V gcc
一些系统的 which ls 会同时显示别名定义和 /usr/bin/ls。这正对应板书中的两层含义:用户输入的 ls 可能先被别名展开,最终运行的外部程序仍是磁盘上的可执行文件。不同发行版中的 which 行为不完全一致,所以判断"命令究竟是什么"时优先用 type -a ls;只想查询解析结果时可用 command -v ls。
15. alias:给常用命令定义别名
bash
alias ll='ls -alF'
alias rm='rm -i'
unalias ll
别名由 Shell 在解析阶段展开,当前终端中定义的别名通常只在当前 Shell 会话有效。要长期生效,可写入 ~/.bashrc,随后开启新 Shell 或执行 source ~/.bashrc。别名适合交互便利,不适合依赖它来保证脚本安全,因为非交互 Shell 的别名行为不同。
四、命令的本质:可执行文件,但不止可执行文件
课堂上常说"命令的本质是可执行文件",这句话抓住了多数外部命令的核心,但需要补全。命令至少有几类:
- 外部可执行文件,例如
/usr/bin/ls、/usr/bin/cp;它们可能是 C/C++ 编译后的 ELF,也可能是带解释器声明的脚本。 - Shell 内建命令,例如
cd、alias、type。它们直接由 Shell 实现。 - Shell 函数和别名,它们是当前 Shell 环境中的定义。
- 关键字,例如
if、for,属于 Shell 语法。

输入 ls -l *.c 后,大致发生如下过程:Shell 读取一行文字,进行引号处理、变量展开和通配符展开;判断 ls 是别名、函数、内建还是需按 PATH 搜索的外部程序;设置重定向和管道;若是外部程序,通常通过 fork/clone 形成执行上下文,再由 execve 把程序装入进程;程序通过系统调用请求内核读取目录;结果写到标准输出,终端把字符显示出来。
PATH 是一组用冒号分隔的目录:
bash
echo "$PATH"
/usr/local/bin:/usr/bin:/bin
当命令中没有 / 时,Shell 才按 PATH 查找。自己编译的程序若位于当前目录,通常要写 ./mycmd,因为当前目录 . 默认不在 PATH 中。这是安全设计:否则攻击者只需在可写目录放一个伪造的 ls,用户进入该目录后就可能误执行它。
不建议为了省略 ./ 就把学习程序复制到 /usr/bin。更合适的方式是明确执行 ./mycmd,或为个人程序使用 ~/.local/bin 并正确配置 PATH。系统目录应由包管理器或管理员维护。
下图后半部分把"命令其实是文件"、别名、历史命令与复制语义放在同一条推导线上。输入的文字可能先由 Shell 改写;外部命令是文件系统中的可执行对象;Ctrl+C 针对的是前台进程,而不是删除命令或关闭终端;上、下方向键则由交互式 Shell 调取历史记录。

验证实验
bash
mkdir -p ~/board-lab/mydir ~/board-lab/backup
cd ~/board-lab
whoami
pwd
touch test.c .hidden.txt
ls
ls -la
ls -ld mydir
stat test.c
cp test.c copy.c
cp test.c backup/
cp test.c backup/renamed.c
type -a ls
command -v ls
which ls
实验完成后先退出练习目录并预览,再交互式清理:
bash
cd ~
tree board-lab
rm -ri board-lab
五、通配符为什么既高效又危险
Shell 常见的文件名展开包括:* 匹配任意长度字符串,? 匹配一个字符,[0-9] 匹配字符集合中的一个字符;Bash 的 {a,b} 是大括号展开,会生成两个词,它甚至早于文件名匹配发生。
bash
ls -- *.txt
ls -- file?.c
cp -- *.{c,h} backup/
默认情况下,* 不匹配以 . 开头的名称,所以 rm -rf * 不会删除普通隐藏文件。这并不代表安全:非隐藏内容仍会被清空,而且 Shell 选项如 dotglob 会改变匹配行为。许多现代 Shell 会避免让 .* 匹配 . 与 ..,GNU rm 也会拒绝操作这两个特殊目录,但 rm -rf .* 仍可能删除大量隐藏配置,不能当作可接受操作。
示例中的 -- 表示选项结束。若文件名恰好叫 -rf,rm -rf 可能把它当选项;写 rm -- -rf 才明确表示后面是文件名。对脚本而言,变量也应加双引号:rm -- "$file",防止空格和通配符被再次拆分或展开。
六、用一个小实验串联全部知识
请使用普通用户,在专门的练习目录中执行:
bash
mkdir -p ~/linux-lab/src ~/linux-lab/backup
cd ~/linux-lab
pwd
touch src/main.c src/util.c README.md
ls -lah
tree .
stat README.md
cp src/main.c backup/
mv README.md README.txt
cat > README.txt <<'EOF'
Linux lab
commands are programs, builtins, functions or aliases.
EOF
cat README.txt
which ls
type -a cd
alias ll='ls -alF'
ll
man ls
最后先预览,再清理:
bash
cd ~
pwd
tree linux-lab
rm -ri linux-lab
这个实验涵盖了定位、创建、查看、复制、移动、内容输入、命令解析、帮助和删除。更重要的是,每一步都能解释:谁解析了参数,路径相对于哪里,程序操作的是内容还是属性,是否会覆盖或删除。
七、结语:真正要记住的不是 15 个单词
Linux 初学阶段最容易陷入"参数背得越多越熟练"的误区。真正可迁移的能力只有几条:文件系统是一棵从 / 开始的树;进程拥有当前工作目录;文件由内容和元数据共同构成;Shell 负责解析、展开、查找与连接程序;外部命令最终通过系统调用请求内核工作;删除和覆盖要在执行前确认作用范围。
掌握这些原则后,遇到没学过的命令也不会慌:先用 type 或 command -V 判断它是什么,再用 man 查语法,用 pwd 确认位置,用无副作用的命令预览对象,最后才执行修改。命令行的价值不在"黑屏看起来专业",而在于它把操作表达成可以理解、复现、组合和自动化的精确语言。
配图说明: 本文三张原理图为原创。命令行为示例,执行前请结合自己的发行版、路径和权限确认。