1.从“会敲命令”到理解 Linux:15 个基础指令、文件树与命令执行的本质

个人主页:
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:给常用命令定义别名)
    • 四、命令的本质:可执行文件,但不止可执行文件
    • 五、通配符为什么既高效又危险
    • 六、用一个小实验串联全部知识
    • [七、结语:真正要记住的不是 15 个单词](#七、结语:真正要记住的不是 15 个单词)

从"会敲命令"到理解 Linux:15 个基础指令、文件树与命令执行的本质

面向第一次接触 Linux 命令行的学习者。本文不追求堆砌参数,而是用一条主线把 pwdcdlstouchstatmkdirtreermdirrmcpmvcatmanwhichalias 等常用命令串起来:我们在终端中做的事情,本质上是在让 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 文件系统从唯一的根目录 / 开始,整体是一棵树。目录负责记录"名字到对象"的映射,普通文件保存内容与属性。严格来说,目录也是一种特殊文件,只是它的内容由文件系统按特定格式维护。

已把pwdwhoamils 和路径关系画在了一起。阅读时要抓住两个不同问题: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:我现在在哪里

pwdprint 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 元数据最后改变时间。实际系统可能采用 relatimenoatime 等挂载策略,因此读取文件不一定每次都把 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.logb.log,输入 rm *.log,Shell 实际交给程序的参数类似 rm a.log b.log。这解释了为什么安全预览有效:先执行 printf '%s\n' ./*.logls -- ./*.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 的别名行为不同。

四、命令的本质:可执行文件,但不止可执行文件

课堂上常说"命令的本质是可执行文件",这句话抓住了多数外部命令的核心,但需要补全。命令至少有几类:

  1. 外部可执行文件,例如 /usr/bin/ls/usr/bin/cp;它们可能是 C/C++ 编译后的 ELF,也可能是带解释器声明的脚本。
  2. Shell 内建命令,例如 cdaliastype。它们直接由 Shell 实现。
  3. Shell 函数和别名,它们是当前 Shell 环境中的定义。
  4. 关键字,例如 iffor,属于 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 .* 仍可能删除大量隐藏配置,不能当作可接受操作。

示例中的 -- 表示选项结束。若文件名恰好叫 -rfrm -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 负责解析、展开、查找与连接程序;外部命令最终通过系统调用请求内核工作;删除和覆盖要在执行前确认作用范围。

掌握这些原则后,遇到没学过的命令也不会慌:先用 typecommand -V 判断它是什么,再用 man 查语法,用 pwd 确认位置,用无副作用的命令预览对象,最后才执行修改。命令行的价值不在"黑屏看起来专业",而在于它把操作表达成可以理解、复现、组合和自动化的精确语言。


配图说明: 本文三张原理图为原创。命令行为示例,执行前请结合自己的发行版、路径和权限确认。

相关推荐
tedcloud1231 小时前
book-to-skill 怎么部署?把技术书和文档转换成可复用的 AI Skill
运维·服务器·人工智能·开源·ai编程
xiaoxiangsiyan1 小时前
企业日常运维高频应用服务全解
运维·网络·云原生·容器·dns
AR_xsy1 小时前
docker--资源配额 配置
运维·docker·容器
YH行业报告分析2 小时前
销售拨号软件升级:智能销售场景下云端自动化如何提升企业获客效率?
运维·自动化
那年窗外下的雪.2 小时前
AIDC 学习日志 Day 3:OSPF Underlay 实验、故障排查与深入解析
服务器·网络·php
深圳恒讯2 小时前
CN2 GIA和CN2 GT的区别
运维·服务器·网络
橙-极纪元2 小时前
把docker的镜像文件从一台服务器中,迁移至另一台服务器
服务器·docker·容器
奔跑的架构师3 小时前
[A-49]ARMv9/v8-PSCI接口规范与工作流程简介
android·linux·arm开发·arm