什么是 Bash 内部命令?
Bash 内部命令(Built-in Command)是指命令本身不是一个独立的、可执行的外部程序文件(/bin/ls 或 /usr/bin/find),而是直接集成在 Bash 解释器程序内部的命令。

当你在一个终端里输入一个命令时,Bash 会按照以下顺序查找它:
- 作为内部命令:首先检查该命令是否是 Bash 自己的内部命令。
- 作为别名:如果不是内部命令,则检查是否是用户定义的别名。
- 作为函数:如果也不是别名,则检查是否是已定义的 Shell 函数。
- 作为外部命令:如果以上都不是,Bash 会在环境变量
PATH指定的目录列表中搜索一个与该命令同名的可执行文件。
为什么要有内部命令? 主要原因是性能和与 Shell 环境的深度集成。
- 性能:调用一个外部程序需要创建一个新的进程(fork-and-exec),这有一定的开销,而内部命令直接在当前 Shell 进程中执行,速度非常快,几乎没有额外开销,频繁使用的
cd,pwd,echo等命令如果做成外部命令,每次执行都会慢很多。 - 环境集成:内部命令可以直接操作和影响当前 Shell 的状态,比如切换当前工作目录 (
cd)、修改 Shell 的选项 (set)、或者控制 Shell 的作业管理 (jobs,fg,bg),这些操作对于外部程序来说是无法做到的。
如何判断一个命令是内部命令还是外部命令?
最简单的方法是使用 type 命令。
# 查看 cd 命令的类型 $ type cd cd is a shell builtin # 输出明确表示它是 shell 内建命令 # 查看 ls 命令的类型 $ type ls ls is aliased to `ls --color=auto' # 它可能是一个别名 # 或者 $ type -t ls # 使用 -t 选项,只返回一个单词 alias # 查看 grep 命令的类型 $ type grep grep is /usr/bin/grep # 输出显示它是一个可执行文件的路径 $ type -t grep file
另一个有用的命令是 help,它可以列出并帮助所有内部命令(除了 shopt, hash, export, readonly 等少数几个)。

# 列出所有内部命令的帮助信息
$ help
# 查看 cd 命令的详细用法
$ help cd
cd: cd [-L|[-P [-e]]] [dir]
Change the shell working directory.
...
常用的 Bash 内部命令分类详解
下面是一些最常用和最重要的 Bash 内部命令,并按功能进行了分类。
目录和文件操作
-
cd(Change Directory)- 功能:切换当前工作目录。
- 特点:这是最典型的内部命令,因为它直接改变 Shell 进程的当前工作目录,任何外部程序都无法做到这一点。
- 示例:
cd /home/user # 切换到 /home/user cd .. # 切换到上一级目录 cd ~ # 切换到当前用户的主目录 cd - # 切换到上一次所在的目录
-
pwd(Print Working Directory)- 功能:打印当前工作目录的完整路径。
- 特点:它显示的是 Shell 当前记录的目录,即使你通过符号链接进入了一个目录,
pwd默认也会打印链接路径(除非使用-P选项)。 - 示例:
pwd # 输出: /home/user/documents
-
pushd,popd,dirs
(图片来源网络,侵删)- 功能:这是一组用于管理目录栈的命令。
pushd:将当前目录压入目录栈,并切换到新目录。popd:从目录栈中弹出最顶层的目录,并切换到该目录。dirs:显示目录栈中的内容。- 示例:
/tmp $ pushd /etc /etc /tmp /etc $ pushd /var /var /etc /tmp /var $ dirs /var /etc /tmp /var $ popd /etc /tmp /etc $ popd /tmp
Shell 状态和环境管理
-
export- 功能:将一个 Shell 变量设置为环境变量,使其可以被当前 Shell 启动的子进程继承。
- 示例:
MY_VAR="hello" # 创建一个局部变量 export MY_VAR # 将其设置为环境变量 bash # 启动一个子 bash shell echo $MY_VAR # 在子 shell 中可以访问到 "hello"
-
readonly- 功能:将一个变量设置为只读,之后无法修改或删除它。
- 示例:
readonly VERSION="1.0" VERSION="2.0" # 会报错:bash: VERSION: readonly variable unset VERSION # 也会报错
-
source或 (点号)- 功能:在当前 Shell 中执行一个文件,而不是创建一个新的子 Shell 来执行。
- 用途:通常用于加载 Shell 配置文件(如
.bashrc)或函数定义文件。 - 示例:
# 在当前 Shell 中执行 .bashrc 文件,使其配置立即生效 source ~/.bashrc # 或者使用点号,效果完全相同 . ~/.bashrc
-
alias- 功能:创建命令别名,为长或复杂的命令设置一个简短的名称。
- 示例:
alias ll='ls -alF' # 创建 ll 别名 alias grep='grep --color=auto' # 让 grep 默认带颜色
流程控制
-
(test)
- 功能:评估条件表达式,虽然
test有一个外部版本,但[是它的一个更常见的别名,并且总是作为内部命令存在。[[是 Bash 的扩展测试命令。 - 示例:
[ -f /etc/passwd ] && echo "File exists" || echo "File not found" [[ $USER == "root" ]] && echo "You are root"
- 功能:评估条件表达式,虽然
-
[和[[- 功能:
[是test命令的别名,用于基本条件测试。[[是 Bash 的关键字,提供了更强大的功能(如正则表达式匹配、逻辑运算符&&和 的直接使用等)。 - 注意:
[和]必须成对出现,并且它们与表达式之间需要有空格。
- 功能:
作业控制
-
jobs- 功能:列出当前 Shell 会话中正在运行或已停止的后台作业。
- 示例:
sleep 100 & # 启动一个后台作业 jobs # 查看作业列表,输出类似 [1] + running sleep 100
-
fg(Foreground)- 功能:将一个后台作业带到前台运行。
- 示例:
fg %1 # 将作业号为 1 的作业带到前台
-
bg(Background)- 功能:将一个已停止的作业在后台继续运行。
- 示例:
sleep 100 # 启动一个前台作业 Ctrl+Z # 暂停它,Shell 会输出 [1] + suspended sleep 100 bg %1 # 将它放到后台继续运行
其他重要内部命令
-
history- 功能:显示和管理命令历史记录列表。
- 示例:
history 10 # 显示最近 10 条历史记录 !123 # 执行历史记录中编号为 123 的命令 !! # 执行上一条命令 !ls # 执行最近一条以 "ls" 开头的命令
-
echo- 功能:打印文本或变量,虽然系统通常有
/bin/echo,但 Bash 自带的echo功能更丰富(支持-e解释转义字符等)。 - 示例:
echo "Hello, World" echo -e "Line1\nLine2" # -e 选项使 \n 被解释为换行
- 功能:打印文本或变量,虽然系统通常有
-
read- 功能:从标准输入读取一行,并将其赋值给一个或多个变量。
- 示例:
read -p "Please enter your name: " name echo "Hello, $name!"
-
ulimit- 功能:控制 Shell 进程及其子进程可以使用的资源,如最大文件大小、最大进程数等。
- 示例:
ulimit -a # 显示所有资源限制 ulimit -n 4096 # 设置单个进程可以打开的最大文件描述符数为 4096
-
type,hash,shopttype:如上所述,用于说明命令的类型。hash:管理命令的哈希表(Bash 记住命令路径的缓存),用于加速命令查找。shopt:设置和取消设置 Shell 的可选行为(选项)。
内部命令 vs. 外部命令:一个关键区别
理解 cd 为什么必须是内部命令至关重要。
# 假设 cd 是一个外部程序 /usr/bin/cd # 你在 /home/user 目录下执行: $ cd /tmp # 这个过程是: # 1. Bash fork() 一个子进程。 # 2. 子进程 exec() /usr/bin/cd。 # 3. /usr/bin/cd 程序运行,改变它自己进程的当前工作目录。 # 4. /usr/bin/cd 程序退出。 # 5. 父进程(你的 Shell)继续运行,它的当前工作目录从未改变! # `cd` 必须在当前 Shell 进程内部执行,才能改变 Shell 的工作目录。
| 特性 | 内部命令 | 外部命令 |
|---|---|---|
| 本质 | 集成在 Bash 解释器中 | 独立的可执行文件 |
| 位置 | 无固定路径,由 Bash 提供 | 通常在 /bin, /usr/bin 等目录 |
| 执行 | 在当前 Shell 进程中执行 | 创建一个新子进程来执行 |
| 性能 | 快,无进程创建开销 | 相对慢,需要 fork/exec |
| 功能 | 可直接修改 Shell 状态(如 cd) |
无法直接修改父 Shell 状态 |
| 查看 | help, type -t builtin |
which, type -t file, man |
| 示例 | cd, pwd, export, source, alias, jobs |
ls, grep, find, cat, vim |
掌握 Bash 内部命令是高效使用 Shell 的关键,因为它让你能够更深入地控制 Shell 的行为和环境,并且能写出更健壮、更高效的脚本。
