Linux 修炼录:基本指令(二)
在上一篇文章中,我们学习了目录切换、文件创建、复制和移动等基础操作。那些命令主要解决的是"如何管理文件和目录"------弄清楚自己在哪里、要去哪里、以及怎么放置文件。
而在实际使用 Linux 时,我们很快就会遇到另一类更频繁的需求:怎么快速查看文件里的内容?文本太长刷屏了怎么办?怎么在成千上万个文件中快速定位目标?输入一个命令时,系统到底调用了磁盘哪个角落里的可执行程序?
比如程序运行报错生成了日志,我们往往只想看最后几十行;查看配置文件时,直接输出几千行会把终端顶出天际;机器里装了多个 Python 版本,我们必须确认输入 python 时启动的到底是哪一个。
这篇文章就围绕这些日常场景,梳理 cat、more、less、head、tail、date、cal、find 和 which 九个核心指令,带你掌握 Linux 终端下的"看、查、寻"。
一、cat:快速查看与拼接
当我们想快速查看一个文本文件的内容时,最直接的反应往往就是敲下 cat。
1、输出内容到终端
cat 是 concatenate(串联、拼接)的缩写。它的设计初衷非常简单:按顺序读取文件内容,然后直接写入标准输出(也就是打印到你的屏幕上)。它不会理解文件语法,不做代码高亮,提供一个文件就输出一个,提供多个文件就依次拼接输出。
基本格式:
bash
cat [选项] [文件...]
常用选项:
-n:为所有输出行加上行号,包括空白行。-b:只为非空行编号;若同时指定了-n,以-b为准。-s:把连续的多个空行压缩为一个空行。-E:在每一行的末尾打印一个$,非常适合用来检查行尾是否存在多余的空格或隐藏字符。-T:把制表符(Tab)显式显示为^I。-A:相当于-vET的组合,一次性暴露行尾符、Tab 制表符和其他不可打印字符。
常见用法速览:
bash
cat note.txt # 快速查看 note.txt 的内容
cat a.txt b.txt # 按顺序依次输出两个文件的内容
cat a.txt b.txt > all.txt # 把两个文件的内容拼接后写入 all.txt
cat -n code.cpp # 查看代码并附带行号
cat > memo.txt << 'EOF' # 从终端交互输入内容,直到输入 EOF 结束并保存
hello
EOF
cat /dev/null > log.txt # 借助空设备迅速清空 log.txt
在日常使用 cat 时,有几个细节特别容易踩坑,值得留心:
- 没有指定文件时,
cat会默认读取标准输入。 如果你只输入了cat就敲回车,终端会停住等待你的键盘输入,输入什么就回显什么,按Ctrl+D才能正常退出。 - 重定向符
>会在命令执行前先清空目标文件。 比如执行cat a.txt b.txt > a.txt,很多初学者的本意是想把b.txt追加到a.txt后面,但 Shell 会在启动cat之前就把目标文件a.txt清空,最终导致a.txt原本的内容彻底丢失。想追加内容,务必使用追加重定向>>,或者先写入新文件。 - 拼接文件要留心末尾换行符。 如果
a.txt的最后一行没有换行符,那么cat a.txt b.txt拼接时,b.txt的第一行就会紧挨着a.txt的末尾连在一起。使用cat -A可以清楚地看到行尾是否有换行标记$。 - 避免用
cat打开超大文件或二进制文件。cat会一股脑将所有字节喷射到屏幕上。文件过大会导致终端疯狂滚动甚至卡顿;如果不小心打开了二进制文件,终端还可能因为控制字符错乱而出现满屏乱码。大文件更适合交给less,二进制文件则应该使用xxd或hexdump。
2、文件拼接与重定向
查看单个短文本时,cat 能够干净利落地直接把内容甩在屏幕上:

当传入多个文件名作为参数时,cat 会忠实地按照参数顺序连续输出:

如果你不仅想在终端里看,还想把串联后的结果保存下来,配合输出重定向 > 即可完成合并:

不过,cat 的优势在于"快"和"直接"。一旦文件超过一两屏,所有内容在瞬间一闪而过,屏幕直接滚到最末尾,前面的内容根本看不清。面对长篇文本,我们就需要借助分页工具了。
二、more:逐屏浏览长文件
假设一个配置文件或日志文件长达几百上千行,用 cat 浏览就像按下了快进键,还没看清开头就已经滑到了底。
1、逐屏向下浏览
more 正是为了解决"内容溢出屏幕"而生的基础分页工具。它会根据当前终端窗口的高度,将文本切分成一屏一屏的内容,展示完一屏后停下来等待你的指令,允许你逐步向后阅读。
基本格式:
bash
more [选项] [文件...]
常见使用方式:
| 命令 | 实际作用 |
|---|---|
more file.txt |
分页打开并浏览文件内容 |
more f1 f2 |
依次分页查看多个文件 |
| `ls /etc | more` |
more +10 file |
跳过前面的行,直接从第 10 行附近开始展示 |
more +/pattern file |
打开文件并直接定位到首次匹配 pattern 的位置附近 |
常用选项:
| 选项 | 实际作用 |
|---|---|
-d |
在屏幕底部显示友好的操作提示(如按空格继续、按 q 退出) |
-s |
遇到连续多个空行时,压缩为单行显示,节省屏幕空间 |
-数字 |
手动指定每一屏显示的行数,例如 more -20 file |
-c |
翻页时从屏幕顶部重绘,而不是向上滚动屏幕 |
-p |
每次换页前先清屏,获得更干净的阅读体验 |
交互控制方式非常朴素:
- 按 空格键(Space):向下翻动一整屏;
- 按 回车键(Enter):向下滚动一行;
- 输入
/关键字:可以在当前文本中向后搜索; - 按
q:随时退出分页模式。
2、浏览操作与局限
在实际终端中,使用 more 打开文件后,屏幕左下角会显示当前已阅读的进度百分比:

不过用过 more 之后,你很快就会感觉到它的局限:它主要支持单向向后翻阅 。如果你刚刚翻得太快,想回过头去重看前面的两行,或者在管道流中想倒退查看,more 就会显得力不从心。
正因如此,现代 Linux 环境中更推荐使用它的强化版兄弟------less。
三、less:自由翻页与检索
Unix 社区里有一句著名的俏皮话:"less is more "(less 比 more 更好用)。既然 more 只能一路向前翻,那想要随意上下翻动、反复搜索,就该请出 less 了。
1、翻页、跳转与搜索
less 是 Linux 下最为强大且常用的文本分页查看器。它不仅支持向上、向下自由翻页,还拥有高效的文本检索能力。
更关键的一点在于内存加载机制 :cat 和一些传统编辑器会试图把整个文件读入内存,而 less 是按需读取的。即使面对一个几个 GB 的超大日志文件,less 也能在毫秒级瞬间打开,完全不会卡死终端。
基本格式:
bash
less [选项] [文件...]
常用命令组合:
| 命令 | 实际作用 |
|---|---|
less file.txt |
启动分页浏览模式查看文件 |
| `ps -ef | less` |
less f1 f2 |
同时打开多个文件,在界面内用 :n(下一个)和 :p(上一个)切换 |
less +F file |
进入类似 tail -f 的动态追踪模式,有新日志追加时自动刷新 |
less +/pattern file |
打开文件后直接定位到匹配关键字的位置 |
常用选项推荐:
| 选项 | 实际作用 |
|---|---|
-N |
在每行开头显示行号,排查代码或日志定位时极其实用 |
-i |
搜索时忽略大小写差异(若搜索词含大写字母则自动恢复大小写敏感) |
-S |
超长行单行截断不折行,保持表格或对齐日志不串行,支持左右横向滚动 |
-R |
正确解析并渲染 ANSI 颜色转义字符,保留原输出的色彩高亮 |
-m |
在底栏显示类似 more 的百分比进度指示 |
在 less 界面中的按键控制十分丰富,建议熟练记住以下几组:
- 上下翻阅 :按
空格或PageDown向后翻一屏;按b或PageUp向前翻一屏;按j/k或上下方向键可以逐行微调。 - 首尾跳转 :按
g瞬间跳到文件首行;按G跳到文件最末行。 - 关键字检索 :
- 输入
/关键字按回车:从当前位置向后搜索; - 输入
?关键字按回车:从当前位置向前搜索; - 搜索命中后,按
n顺向跳到下一个匹配项,按N逆向跳回上一个匹配项。
- 输入
- 退出 :在任何时候按下
q即可干净利落地退回 Shell。
日常使用中的几点重要体会:
-S的权衡 :默认情况下遇到超长单行,less会折行显示,容易把日志打乱;加上-S可以让单行完整延伸,使用键盘的左右方向键横向滚动查看,版面会整洁很多。- 读到末尾不会强退 :
more读到文件末尾往往会自动退出,而less到达末尾后依然停留在查看界面,按q才会交还终端控制权。 - 彩色命令搭配
-R:当管道前面的命令输出带颜色时(例如带色彩的测试输出或日志),务必加上-R(如dmesg --color=always | less -R),否则颜色代码会被显示成杂乱的字符标记。
2、大文件浏览实测
为了真切感受 less 在大文本中的导航能力,我们先用一段简单的 Shell 循环脚本生成一个包含 2000 行内容的测试文件 temp.txt:
bash
cnt=1
while [ $cnt -le 2000 ]; do
printf "hello %d\n" "$cnt"
let cnt++
done > temp.txt
这段脚本从 1 计数到 2000,每行输出一个序号,最终通过 > 重定向全部写入 temp.txt。
接着输入 less -N temp.txt 打开它。此时你可以随意使用 j、k 逐行滚动,用 PageUp、PageDown 翻页,输入 /hello 1500 瞬间定位到第 1500 行,体会行云流水般的检索与回溯体验:

less 解决了完整阅读和检索大文件的痛点。但如果现实场景更简单:我们既不想翻页,也不想通读,只想看一眼文件最前面的几行标题或配置呢?这就要用到 head。
四、head:提取文件头部
在处理数据文件、配置文件或者代码源文件时,很多时候我们只需要扫一眼文件的头部------比如看看 CSV 文件的第一行列名、检查脚本开头的解释器声明(Shebang),或者确认输出结果是否符合预期。
1、按行截取头部
head 默认提取并打印文件的前 10 行内容,执行完立即退出,不拖泥带水。
基本语法:
bash
head [选项]... [文件]...
若未指定文件名,或者文件名显式写为 -,head 就会从标准输入读取数据,这使得它天然可以作为管道末端的过滤器。
常见参数对照:
| 参数 | 实际作用 | 典型示例 |
|---|---|---|
-n <N> |
输出文件开头的指定前 N 行 |
head -n 20 file.txt |
-n -<N> |
输出除了末尾 N 行之外的所有前面内容 |
head -n -5 file.txt |
-c <N> |
输出文件开头的指定前 N 个字节 |
head -c 100 file.txt |
-q |
同时查看多个文件时,不打印文件名标头 | head -q -n 3 a.txt b.txt |
-v |
始终强制在内容前显示文件名横幅 | head -v -n 3 file.txt |
这里需要理清两个关键细节:
- 按行截取 vs 按字节截取 :
-n是按行数(换行符)统计,-c则是按底层字节(Byte)截取。在处理纯文本文件时,尽量使用-n;如果对 UTF-8 中文字符使用-c,很可能会把一个占 3 字节的汉字从半中间切断,导致末尾出现乱码。 - 负数行参数
-n -N:例如head -n -5 file.txt,它的含义是"切掉最后 5 行,打印剩下的前面全部内容"。这是 GNU 版head提供的扩展语法,在某些严格遵循 POSIX 标准的传统 Unix 环境中可能不支持,编写跨平台脚本时需要注意兼容性。
2、行数微调与多文件查看
在终端里使用 head 截取文件前几行,可以快速确认文件的格式与开头信息:

看完了文件头部,一个对称的需求立刻浮现出来:如果我想关注文件的最末尾,或者想实时盯住不断写入的新内容,该用什么命令?
五、tail:追踪末尾与实时日志
与 head 相对,tail 默认提取文件的最后 10 行。但在运维和日常开发中,tail 的出场频率甚至远高于 head,因为系统的报错堆栈、服务的运行动态,永远都在文件的最底部刷新。
1、读取末尾与实时追踪
基本语法:
bash
tail [选项]... [文件]...
常用参数及应用场景:
| 参数/选项 | 实际作用 | 典型示例 | 关键说明 |
|---|---|---|---|
-n <N> |
查看末尾倒数 N 行 |
tail -n 50 app.log |
常可简写为 tail -50 app.log |
-n +<N> |
从指定的第 N 行开始,一直输出到文末 |
tail -n +10 data.csv |
过滤前 9 行表头/注释的高效手段 |
-c <N> |
查看末尾 N 个字节 |
tail -c 500 error.log |
支持 K、M 等单位后缀 |
-c +<N> |
从第 N 个字节开始输出直至文末 |
tail -c +50 file.bin |
跳过二进制头部偏移量 |
-f |
实时追踪文件新增内容(follow) | tail -f access.log |
动态监控日志,按 Ctrl+C 退出 |
-F |
基于文件名持续重试追踪 | tail -F app.log |
应对日志轮转(Logrotate)的最佳选择 |
-q / -v |
静默模式 / 显式模式 | tail -q -n 5 a.log b.log |
隐藏或强制输出文件名横幅 |
这里有两个极其核心的知识点需要吃透:
-n后带正负号的语义截然不同 :tail -n 20 file:表示取倒数 20 行;tail -n +20 file:表示从正数第 20 行开始 ,一路倾倒到文件末尾。在批量数据处理中,如果你想扔掉前两行无用的说明文字,直接用tail -n +3就可以优雅搞定。
-f与-F的生命周期机制 :-f(小写)是基于底层**文件描述符(inode)**进行跟踪的。一旦日志服务触发轮转(把app.log重命名为app.log.1并新建空白app.log),小写-f还会死死盯住被移走的旧文件,再也看不到新日志;-F(大写)不仅会追踪内容,还会定期按文件名 去探测。即便文件被切走重置、甚至暂时消失,它也会耐心等待并重新打开同名新文件。在生产环境中排查长期运行的服务日志时,强烈建议使用-F。
2、管道组合截取区间
常规查看文件末尾 20 行:

现在我们来思考一个非常经典的实战问题:如果我想精准截取文件第 100 行到第 110 行的内容,该怎么做?
单个 head 或单个 tail 都无法一步到位,但把它们通过管道 | 串联起来,问题就迎刃而解了:
- 先用
head -n 110截取前 110 行; - 再把这 110 行送给
tail -n 11,取出其中的最后 11 行。
bash
head -n 110 temp.txt | tail -n 11
计算逻辑很简单:110−100+1=11110 - 100 + 1 = 11110−100+1=11 行。最终拿到的刚好就是闭区间 100,110100, 110100,110 的 11 行数据:

这就是 Linux 哲学中"管道"的魅力:每一个工具只做一件简单的事情,组合起来却能解决千变万化的需求。
六、date:查看与格式化时间
不仅文件内容需要观察,操作系统的时钟状态也与我们息息相关。程序打出的日志需要核对时间戳,定时任务需要比对计划触发点,Shell 脚本自动备份文件时也需要根据当前日期给文件打上防重名的标记。
1、格式化时间输出
date 指令用于查看和格式化系统的当前日期与时间;在拥有 root 权限时,也能用于校准系统时钟。
基本语法:
bash
# 读取并格式化当前时间
date [选项]... [+格式控制符]
# 手动修改系统时钟(需要超级管理员权限)
date [选项]... -s "时间字符串"
只要在自定义字符串前加上一个 + 号,就可以自由选用各种占位符组合出所需的时间外观。
最常用的时间占位符一览:
| 占位符 | 具体含义 | 示例输出 |
|---|---|---|
%Y |
4 位数完整年份 | 2026 |
%m |
2 位月份(01 ~ 12) | 10 |
%d |
2 位日期(01 ~ 31) | 31 |
%H |
24 小时制小时(00 ~ 23) | 14 |
%I |
12 小时制小时(01 ~ 12) | 02 |
%M |
2 位分钟数(00 ~ 59) | 30 |
%S |
2 位秒数(00 ~ 59) | 45 |
%s |
Unix 时间戳(自 1970-01-01 00:00:00 UTC 至今经过的秒数) | 1793457045 |
%F |
快速年月日组合,等价于 %Y-%m-%d |
2026-10-31 |
%T |
快速时分秒组合,等价于 %H:%M:%S |
14:30:45 |
%w / %u |
星期几:%w 范围 0 ~ 6(周日为 0),%u 范围 1 ~ 7(周一为 1) |
6 |
在编写自动化运维脚本时,下面这种标准化格式是绝对的常客:
bash
date +"%Y-%m-%d %H:%M:%S"
打包备份文件时,也可以将时间戳直接嵌入文件名:
bash
tar -czf "backup_$(date +%Y%m%d_%H%M%S).tar.gz" /data
!WARNING
切勿在生产环境中随意运行
date -s修改时间。 服务器底层的分布式数据库一致性、Kerberos 认证、日志审计链以及定时任务调度严重依赖单调同步的系统时钟。随意改动系统时间极易引发连锁故障;现代 Linux 服务器应统一配置 NTP 或 chrony 服务自动同步网络时钟。
2、自定义格式实测
直接输入 date 可以打印当前系统的完整时间表达;通过 + 追加格式符后,输出即可按照我们的心意定制:

date 帮我们抓取了某个精确的时刻。而如果我们想从宏观上查看一个星期、一个月乃至整年的日期排布,就需要用到专门的日历工具。
七、cal:把日历搬进终端
有时候我们在写周报、排期任务或者核对某个月的星期跨度时,懒得切出终端去翻桌面日历,这时候一条小巧的 cal 指令就能把一张整洁的月历直接绘制在屏幕上。
1、月历与年历输出
cal 是 calendar 的缩写。不带任何参数时,它会输出当月的月历,并在当天的数字上进行高亮标出。
基本语法:
bash
cal [选项]... [[[日] 月] 年]
常用选项对照:
| 参数/选项 | 实际作用 | 典型示例 | 说明 |
|---|---|---|---|
-1 |
仅输出单个月份(默认行为) | cal -1 |
快速看一眼当月 |
-3 |
并排输出上月、当月和下月 | cal -3 |
查看跨月任务排期时最为方便 |
-y / --year |
铺开输出整年的 12 个月份 | cal -y |
纵览全年日历视图 |
-m / --monday |
强制以周一作为每周的第一列 | cal -m |
符合中国用户的使用习惯 |
-s / --sunday |
强制以周日作为每周的第一列 | cal -s |
欧美传统的周日排首位格式 |
-j / --julian |
输出一年中的第几天(Day of Year) | cal -j |
显示日期是全年第几天(1 ~ 365/366) |
需要指出的是,参数 -j 打印的是一年中的日序号(比如 2 月 1 日显示为 32),而不是天文学上严格定义的儒略日数(Julian Day Number),两者切勿混淆。
2、跨月与整年视图
在日常使用中,-3 是极为顺手的参数,能帮你一眼理清月度交替时的星期节奏:

八、find:多条件精准查找
随着系统使用时间的推移,你的机器里可能会产生数以万计的文件。它们散落在各个层级的目录深处,文件名可能只记得一半,或者只隐约记得它是一个大约 50MB 的日志、在最近三天内被修改过。
如果只靠 ls 和 cd 逐层人肉翻找,效率无异于大海捞针。这时候,Linux 体系中最强大的搜索利器 find 就要大显身手了。
1、常用搜索条件
a. 语法与遍历机制
bash
find [搜索路径...] [匹配表达式/选项] [执行操作]
三个基础规则:
- 默认路径 :如果不给路径,
find默认从当前所在目录.开始递归向下搜寻; - 默认操作 :如果不给后续操作动作,
find默认使用-print,把搜到的完整路径一行行打在屏幕上; - 实时扫描 :
find是实打实地直接遍历磁盘目录树进行条件比对的。它不像locate那样依赖预先生成的数据库索引,因此它的结果绝对准确、绝对实时 ;相对地,如果直接在全盘根目录/下大范围搜索,会产生大量磁盘 I/O,速度会慢一些。
b. 按文件名匹配
| 选项 | 匹配规则 | 示例 | 场景说明 |
|---|---|---|---|
-name |
精确匹配名称,严格区分大小写 | find . -name "*.log" |
最标准的按文件名匹配,通配符建议加双引号 |
-iname |
忽略大小写进行匹配 | find . -iname "readme.md" |
能够同时命中 README.MD、Readme.md 和 readme.md |
c. 按文件类型筛选
使用 -type 参数可以锁定文件类型,避免目录名或设备节点混淆搜索结果:
f:普通文件(regular file)d:目录(directory)l:符号链接 / 快捷方式(symbolic link)s:套接字文件(socket)p:命名管道(FIFO)
常用范例:
bash
# 只列出当前目录及其子目录下的"目录"
find . -type d
# 在 /var/log 目录下查找所有以 .log 结尾的"普通文件"
find /var/log -type f -name "*.log"
d. 按文件大小筛选
当服务器磁盘告警爆满时,我们需要立刻找出是哪些庞然大物吃光了空间
这时使用 -size 可以轻松筛选
常用单位包括 c(字节)、k(KiB)、M(MiB)和 G(GiB):
+N:严格大于该体积;-N:严格小于该体积;N:大小落在该单位对应的区间内。
bash
# 找出 /var 目录下所有大于 100 MiB 的普通文件
find /var -type f -size +100M
# 找出大小处于 10 MiB 到 50 MiB 之间的文件
find . -type f -size +10M -size -50M
!NOTE
find -size N(不带加减号)存在单位取整规则,并不是指文件大小精准严苛到等于 N 字节。日常排查空间占用时,绝大多数情况都是使用+100M、+1G这种正向范围过滤。
e. 按时间范围筛选
文件的元数据中记录了多个时间属性:
atime(Access Time):最后一次被读取或访问的时间;ctime(Change Time):文件元数据(如权限、所有者、链接数)发生变更的时间。注意它不是"创建时间"(Creation Time);mtime(Modify Time):文件真实内容最后一次被修改的时间。
在排查日志和维护文件时,以天为单位的 -mtime 和以分钟为单位的 -mmin 最为常用:
bash
# 找出最近 7 天内修改过的文件
find /data -type f -mtime -7
# 找出 30 天以前修改过、长期未更新的陈旧文件(适合归档清理)
find /var/log -type f -mtime +30
# 找出最近 30 分钟内被篡改或写入的文件(排障神器)
find /etc -type f -mmin -30
关于加减号的推算细节:-mtime 是按完整的 24 小时滑窗周期计算的。-mtime -7 表示距离当前时刻在 7×247 \times 247×24 小时以内的变动;+30 则表示修改时间已经流逝了超过 30 个完整 24 小时周期。
f. 按权限与归属筛选
在做安全巡检时,我们往往需要排查权限配置过于宽松的危险文件:
bash
# 寻找权限完全匹配 777(所有人可读可写可执行)的文件
find /tmp -type f -perm 777
# 寻找属主为 nginx 用户的静态文件
find /var/www -user nginx
2、常见避坑要点
在使用 find 这一强力工具时,有三个极高频的经典"暗坑":
-
通配符必须用引号包裹:
- 错误写法:
find . -name *.txt - 正确写法:
find . -name "*.txt"
如果不加引号,当当前目录下刚好存在
a.txt和b.txt时,Shell 会在命令启动前就把*.txt展开成find . -name a.txt b.txt,直接导致参数解析错乱甚至报错。加上引号后,通配符才会原封不动传给find内部去遍历比对。 - 错误写法:
-
批量删除前,务必先用
-print预览 :find提供了直接就地删除匹配项的-delete动作,也支持通过-exec rm -f {} +批量执行清理。但删除操作是不可逆的!在执行任何破坏性指令之前,务必先把操作替换为-print(或直接运行搜索),人工核对一遍匹配出来的路径名单,确认万无一失后再执行删除。 -
屏蔽系统深层扫描时的权限警告 :
当普通用户从根目录
/开始全局检索时,会路过很多权限受限的系统目录,屏幕上会被铺天盖地的Permission denied刷屏,真正有用的搜索结果反而被淹没。我们可以利用标准错误重定向将其过滤掉:bashfind / -name "my_file" 2>/dev/null数字
2代表标准错误输出(stderr),/dev/null是 Linux 下的"数据黑洞"。这行命令把所有报错信息默默扔掉,只在屏幕上呈现正常搜出的匹配路径。
3、组合条件实测
在实际终端中,通过把路径、类型和通配名称组合起来,find 能够迅速穿透多层嵌套子目录,准确锁定目标文件:

九、which:定位命令所在路径
学会了用 find 在庞大的文件系统里找普通文件,我们再来看一个更具"命令行特色"的困惑。
在终端里,我们随手敲下 ls、gcc、python3,系统立刻就能心领神会地执行对应的程序。但是你想过没有:这些命令对应的二进制程序文件,究竟躺在磁盘的哪一个文件夹里? 如果系统里既装了系统自带的 Python 2,又装了 Anaconda 的 Python 3,我们在终端敲下 python 时,执行的究竟是哪一个?
1、沿着 PATH 查找程序
which 指令专门用来查找并显示给定命令对应的可执行文件绝对路径。
基本语法:
bash
which [选项] [--] 程序名...
which 的工作原理非常纯粹:它会依次读取环境变量 $PATH 里配置的目录列表。PATH 中包含了若干个用冒号 : 分隔的目录路径,which 沿着这些目录从前向后逐一探查,一旦在某个目录下找到了匹配的可执行文件,就会停下来输出该路径。
常见应用场景:
- 诊断版本冲突:当输入某个程序发现行为不符合预期时,检查它命中的到底是哪个路径下的二进制包;
- 确认新软件是否进入环境变量 :刚编译安装完一个工具却提示
command not found,用which确认其是否已被收录在系统的搜索路径中; - 编写脚本时获取硬编码绝对路径 :许多后台守护进程脚本或 Crontab 任务要求必须使用程序的绝对全路径(如
/usr/bin/python3),此时可以用which快速提取。
常用选项:
| 选项 | 实际作用 | 典型示例 | 场景说明 |
|---|---|---|---|
-a / --all |
显示搜索路径中找到的所有匹配项,不只是第一个 | which -a python3 |
探查整个 PATH 中是否存在多个同名版本覆盖 |
--skip-alias |
忽略当前的别名配置,只查找实际的可执行程序 | which --skip-alias ls |
排除别名干扰,看原生文件路径 |
--version |
查看 which 工具自身的版本信息 |
which --version |
检查版本 |
使用 which 时,还有两点至关重要的认知延展:
-
which只能找外部可执行程序,找不到 Shell 内建命令 :在 Linux 中,命令并不全都是磁盘上的独立二进制文件。命令大致分为四种:别名(alias)、Shell 内建命令(builtin)、Shell 函数以及外部可执行程序。像
cd、pwd(Bash 内建版本)、echo等很多命令是直接驻留在 Shell 内存核心里的,磁盘上根本没有独立的可执行镜像。如果你想彻查一个命令在 Shell 视角下到底会被如何解析,更推荐使用 Shell 自带的
type命令:bashtype -a python type -a cdtype -a会完整告诉你它是一个内建命令、别名,还是具体指向哪个外部路径。 -
普通用户与 Root 用户的
$PATH天生不同 :管理员 Root 的
PATH通常包含/sbin、/usr/sbin等系统管理专用的目录,而普通用户的PATH可能没有。如果你以普通用户身份执行which fdisk返回为空,并不意味着系统没装它,很可能只是你当前账号的搜索路径里没有收录对应的管理目录而已。
2、命令路径查询实测
在实际终端中,通过 which 我们可以迅速确认命令背后的真身:

总结:把命令串成工作流
回过头来看,这篇文章介绍的九个指令并非散落孤立的知识点,它们正好覆盖了我们在 Linux 环境下与文件和系统交互的各个维度:
- 文本阅读梯队 :
- 小文件快查首选
cat; - 遇到长文想分屏看用
more; - 真正需要前后翻页、深度检索大文件时,果断请出
less; - 想快速核对文件表头用
head; - 想查看尾部结果、盯紧新增实时日志,离不开
tail(尤其是tail -F)。
- 小文件快查首选
- 环境与时间状态 :
- 获取精确时间戳、定制化脚本命名用
date; - 直观排查周度、月度排期用
cal。
- 获取精确时间戳、定制化脚本命名用
- 定位与追踪检索 :
- 在浩瀚的文件系统中按各种属性寻宝,全能利器是
find; - 追踪终端敲下的指令到底指向磁盘哪个程序,随时呼叫
which(配合type更佳)。
- 在浩瀚的文件系统中按各种属性寻宝,全能利器是
在真实的 Linux 工作中,最优雅的操作往往来自于它们之间的组合拳:
bash
# 例子:在 /var/log 下找出最近 1 天内修改过的大日志,用 tail 查看其最新报错,再交给 less 慢慢分析
find /var/log -type f -name "*.log" -mtime -1 -size +10M | head -n 1 | xargs tail -n 100 | less
把这些命令融入指尖的肌肉记忆,当你再次面对成百上千行代码、海量的运行日志以及复杂的系统目录树时,终端就不再是一个冰冷的黑框,而是一套顺手、高效的生产力武器库。