alias 命令详解与参数实测(Ubuntu 22.04)

基于 Ubuntu 22.04(bash 5.1.16)逐项实测 alias:无参列出与交互 shell 继承、-p 可复用格式、单个查看及 not found 退出码、定义与覆盖重定义、同一行定义不展开的时机规则、脚本内 shopt -s expand_aliases、别名不支持位置参数及函数替代、递归展开与自引用防护、值尾空格链式展开、unalias 单删/批删/-a 全清与 .bashrc 持久化。

Linux命令Linux系统UbuntuUbuntu 22.04命令行Shell2026/10/16

alias 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 alias 的每一种用法——无参数列出别名、-p 以可复用格式打印、查看单个别名及其退出码、定义与覆盖重定义、同一行定义不展开的时机规则、脚本中用 shopt -s expand_aliases 启用展开、别名不支持位置参数及函数替代方案、递归展开与自引用防护、值尾空格的链式展开、unalias 单删/批删/-a 全清,以及写入 /root/.bashrc 的持久化,全部命令与回显已在 Ubuntu 22.04(bash 5.1)实测通过。

一、环境信息

本文所有命令与回显均在以下环境实测采集,读者在相同版本的 Ubuntu 上可直接复现:

项目实测值
操作系统Ubuntu 22.04.5 LTS
架构x86_64
ShellGNU bash,版本 5.1.16(1)-release
alias 命令类型shell builtin(Shell 内置命令,非外部可执行文件)
实测演示目录/root/demo/alias
别名配置文件/root/.bashrc

环境确认命令与实测回显如下:

$ head -2 /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"

$ uname -m
x86_64

$ echo BASH_VERSION=$BASH_VERSION
BASH_VERSION=5.1.16(1)-release

$ type alias
alias is a shell builtin

💡 说明:alias 是 bash 内置命令,没有独立的可执行文件,也没有 --version 类选项;版本信息即 bash 版本(见 2.3 节)。

⚠️ 关于回显中的报错前缀:本文部分回显采集自实测脚本(如 /root/alias-test.sh),错误行前缀 /root/alias-test.sh: line 3: 是 shell 报错定位(脚本路径与行号);读者在交互式终端手工执行同样命令时,对应前缀为 bash:。命令本身在两种场景通用。

二、命令概览

2.1 语法与测试数据

alias 用于给命令(及其参数串)定义短别名,unalias 用于删除别名。两者语法:

alias [-p] [name[=value] ...]   # 不带 =value 时为查看;带 =value 时为定义
unalias [-a] name [name ...]    # 删除一个或多个别名;-a 删除全部

要点解读:

  • alias 不带任何参数:打印当前全部别名(与 alias -p 等价);
  • alias name:只给名字不给值——查看该别名;
  • alias name='value':定义/重定义别名;
  • 别名只在定义它的那个 shell 会话内有效,不随子进程传递,也不写入磁盘(持久化需写入 .bashrc 等启动文件,见 4.3 节)。

按 3.4 节准备演示目录,后续示例均使用它:

$ mkdir -p /root/demo/alias

$ echo 'first line' > /root/demo/alias/a.txt

$ echo 'second line' > /root/demo/alias/b.txt

$ ls -l /root/demo/alias
total 8
-rw-r--r-- 1 root root 11 Oct 15 21:15 a.txt
-rw-r--r-- 1 root root 12 Oct 15 21:15 b.txt

2.2 help 全量输出(逐行照抄)

alias 是内置命令,其官方帮助通过 help alias 获取。以下为 help alias 的完整实测输出(逐行照抄,未做删改):

$ help alias
alias: alias [-p] [name[=value] ... ]
    Define or display aliases.
    
    Without arguments, `alias' prints the list of aliases in the reusable
    form `alias NAME=VALUE' on standard output.
    
    Otherwise, an alias is defined for each NAME whose VALUE is given.
    A trailing space in VALUE causes the next word to be checked for
    alias substitution when the alias is expanded.
    
    Options:
      -p	print all defined aliases in a reusable format
    
    Exit Status:
    alias returns true unless a NAME is supplied for which no alias has been
    defined.

逐句解读这份帮助:

  • **Without arguments ... reusable form alias NAME=VALUE'**:无参数时以 alias NAME=VALUE` 的"可直接粘贴回 shell 复用"的格式打印全部别名;
  • A trailing space in VALUE causes the next word to be checked for alias substitution:别名值末尾如果是空格,展开后其后的下一个词也会继续做别名检查(链式展开,3.10 节实测);
  • Options: -p:以可复用格式打印全部别名(3.2 节实测);
  • Exit Status:只要"查询了一个不存在的别名",alias 就返回失败(rc=1);其余情况返回成功(3.1、3.3 节实测)。

2.3 版本信息

alias 无独立版本号,版本跟随 bash。实测:

$ bash --version | head -1
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

本文全部行为均在 bash 5.1.16 上验证,其他 5.x 版本行为一致。

三、参数逐项实测

3.1 无参数:列出当前所有别名

无参数的 alias 列出当前 shell 会话中已定义的全部别名。先看非交互脚本环境(本实测回显的采集环境)——别名列表为空,退出码为 0:

$ alias

$ alias; echo rc=$?
rc=0

再看交互式 shell(登录终端、bash -i)中的表现——别名列表就是 /root/.bashrc 加载进来的那批:

$ bash -ic 'alias'
bash: cannot set terminal process group (10773): Inappropriate ioctl for device
bash: no job control in this shell
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

说明与解读:

  • 非交互 shell(脚本、cron、bash file.sh)不读取 .bashrc,因此看不到 ll、la 等别名——这正是很多"脚本里别名不生效"问题的根源(详见 3.6 节与五、Q1/Q3);
  • bash -ic '...' 表示"启动交互式 shell 并执行命令",前两行是该场景下无终端作业控制的提示(stderr 输出),不影响 alias 结果;
  • 交互 shell 列出的 7 条别名全部来自 /root/.bashrc(原文见 4.3 节)。

💡 要点:alias 无参永远返回 0(rc=0),即使列表为空;它列出的只有"当前会话"的别名,换了会话(新终端、子 shell、脚本)列表就可能不同。

3.2 -p:以可复用格式打印别名列表

alias -p 与无参数形式等价,输出"可直接粘贴复用"的 alias NAME=VALUE 格式。实测:

$ alias p1='echo p-one'

$ alias -p
alias p1='echo p-one'

$ unalias p1

💡 要点:-p 的价值在批量导出——在配置好的机器上执行 alias -p,把整段输出粘贴进新机器的 .bashrc,即可完整复制一套别名习惯;无参数 alias 与 alias -p 的输出格式完全相同。

3.3 alias name:查看单个别名

给名字不给值即为查询。查询存在的别名,原样打印其定义;查询不存在的别名,报 not found 且退出码为 1:

$ alias st
alias st='echo test-alias'

$ alias ll; echo rc=$?
/root/alias-test.sh: line 3: alias: ll: not found
rc=1

说明与解读:

  • alias st 输出 alias st='echo test-alias',与定义格式一致;
  • alias ll 报 not found——ll 定义在 /root/.bashrc 里,只有交互 shell 才加载它;本实测脚本是非交互 shell,没加载 .bashrc,自然查不到。读者在登录终端执行 alias ll 会看到 alias ll='ls -alF';
  • 退出码 rc=1 与 2.2 节帮助中 "alias returns true unless a NAME is supplied for which no alias has been defined" 完全对应。

💡 要点:alias name 是脚本里判断"某个别名在本会话是否可用"的标准手段,用 $? 即可判断,无需解析输出。

3.4 定义别名 name='value':alias st='echo test-alias'

定义别名的基本形态是 alias name='value'。在非交互脚本中定义别名前,必须先 shopt -s expand_aliases 打开别名展开开关(交互 shell 默认已打开,无需此步):

$ shopt -s expand_aliases

$ alias st='echo test-alias'

$ st
test-alias

$ alias gs='git status'

$ alias st
alias st='echo test-alias'

$ alias gs
alias gs='git status'

说明与解读:

  • shopt -s expand_aliases 是非交互 shell 使用别名的前置条件:bash 默认只在交互 shell 中展开别名;
  • st 直接回车即执行了别名值 echo test-alias,输出 test-alias;
  • gs 定义为 git status 的别名,此处只定义与查看(是否安装 git 不影响定义本身);真正的命令替换发生在调用时——输入 gs 时 bash 才把它展开为 git status 再执行;
  • 调用时别名值后还可以追加参数:st 展开成 echo test-alias,若输入 st extra 则展开成 echo test-alias extra(参数拼在别名值后面)。

💡 要点:等号两侧不能有空格——alias st = 'echo test-alias' 会被解析成"查看 st、查看 =、查看 'echo..."三个查询;value 含空格必须整体加引号。

3.5 别名覆盖重定义

同名 alias 再定义一次即覆盖旧值,无须先删除:

$ alias st='echo version-1'

$ st
version-1

$ alias st='echo version-2'

$ st
version-2

💡 要点:后定义的覆盖先定义的,顺序敏感——.bashrc 中靠后的定义才是最终生效值;排查"别名行为和预期不符"时,先用 alias name 看当前实际值,再用 type -a name 看是否存在同名函数/外部命令遮蔽(见五、Q5)。

3.6 别名的展开时机:同一行定义后立即调用不生效

别名展开发生在 bash 读取整行输入的时刻。因此"定义别名"和"调用别名"写在同一行时,读取该行的瞬间别名还不存在,调用不会展开:

$ alias q='echo quick'; q; echo rc=$?
/root/alias-test.sh: line 3: q: command not found
rc=127

$ q
quick

说明与解读:

  • 第一条命令里 q 报 command not found(rc=127)——整行被读入时做别名检查,此时 q 尚未定义;
  • 换到下一行(下一个读取单元)再输入 q,别名已存在,正常输出 quick;
  • rc=127 是 bash "命令不存在"的标准退出码。

💡 要点:这条时机规则解释了两个常见现象——① 把 alias 定义写进 shell 脚本后,同一行不能用、下一行才能用;② 在 .bashrc 末尾定义的别名,对本轮已开着的会话不生效,需要 source ~/.bashrc(source 会把文件作为新的读取单元重新读入)或开新终端。

3.7 别名不支持位置参数:$1 实测与函数替代方案

别名是纯文本替换,没有"参数槽位"。给别名值写 $1,它不会接收"调用别名时跟的参数",而是在展开后按普通变量展开——取当前 shell 的位置参数。本节演示脚本以 bash /root/alias2-test.sh TOPLEVEL-ARG 方式启动(脚本带位置参数 $1=TOPLEVEL-ARG):

$ alias greet='echo hello $1'

$ greet world
hello TOPLEVEL-ARG world

$ greet
hello TOPLEVEL-ARG

解读这个"反直觉"的结果:

  • greet world 展开成 echo hello $1 world——调用时跟的 world 只是拼在展开文本后面的词;
  • 随后 $1 作为普通变量展开,取到的是脚本自身的位置参数 TOPLEVEL-ARG,与调用时给的 world 毫无关系;
  • 所以输出是 hello TOPLEVEL-ARG world,而不是期望的 hello world。

需要"参数槽位"时,用函数替代(函数的 $1 才是调用时的第一个参数):

$ greet_fn() { echo "hello $1"; }

$ greet_fn world
hello world

$ greet_fn alias-test
hello alias-test

💡 技术拓展:给命令"做减负包装"有三种方案,能力与适用场景对比如下——

方案参数支持生效范围适用场景
别名 alias❌ 纯文本替换,无 $1当前会话;脚本需 expand_aliases短命令换名、给命令追加固定参数
函数 function✅ $1..$n 完整支持当前会话;可 export -f 传给子 bash带参数的包装逻辑、多步组合
外部脚本✅ $1..$n 完整支持任意进程(可执行权限 + PATH)复杂逻辑、跨会话/跨用户复用

本文 3.4 节的 st/gs 属"换名+固定参数",用别名即可;需要参数的 greet 用函数(本节实测);超过几行的逻辑建议落成脚本。选型口诀:能别名则别名,带参数用函数,要复用写脚本。

3.8 递归展开:别名值的首词会继续查别名(防自引用死循环)

bash 对别名展开的规则是:别名值的首词会再次做别名检查,直到命中非别名命令;唯一的限制是"与正在展开的别名同名的词不再展开"(防无限循环)。先看跨别名链式展开生效:

$ alias b='ls /root/demo/alias'

$ alias a='b'

$ a
a.txt
b.txt

a 展开成 b,b 又是别名,继续展开成 ls /root/demo/alias,最终正常执行——a.txt、b.txt 即演示目录内容。

再验证自引用防护:定义一个值就是自身的别名,调用时不会无限展开,而是把"同名不再展开"的那个词当普通命令查找:

$ alias loop='loop'

$ loop; echo rc=$?
/root/alias2-test.sh: line 3: loop: command not found
rc=127

💡 要点:正是"同名不再展开"这条防护,让 3.9 节"给原命令追加默认参数"的写法成为可能——alias df='df -h' 中的第二个 df 不会再撞回别名自身。

3.9 自引用别名:给原命令追加默认参数

别名值的首词与别名同名时不再展开,因此可以安全地"以原名定义原名"——最经典的应用是给命令追加默认参数:

$ alias du='du -h'

$ du /root/demo/alias
12K	/root/demo/alias

du /root/demo/alias 展开成 du -h /root/demo/alias:第二个 du 与正在展开的别名同名,不再检查别名,直接使用真实的 du 命令,输出以人类可读单位(12K)显示。同理 alias df='df -h'(见 4.1 节)让 df 默认带 -h。

💡 要点:这种"同名加参"写法(alias ls='ls --color=auto'、alias grep='grep --color=auto')在 Ubuntu 默认 .bashrc 中大量出现(见 4.3 节),机制全部依赖本节的防自引用规则;它只加参数、不改变命令语义,是别名最安全的用法。

3.10 值尾空格的链式展开:alias d='echo ' 与 alias f='echo' 的差别

2.2 节帮助提到:"A trailing space in VALUE causes the next word to be checked for alias substitution"。用一对别名实测这个差异(e2 是一个值为纯文本的别名):

$ alias e2='E2-EXPANDED'

$ alias d='echo '

$ d e2
E2-EXPANDED

$ alias f='echo'

$ f e2
e2

解读两行的差别:

  • d 的值 echo 末尾带一个空格——d e2 展开成 echo 后,其后的词 e2 也做别名检查,命中别名展开为 E2-EXPANDED,最终执行 echo E2-EXPANDED,输出 E2-EXPANDED;
  • f 的值 echo 末尾无空格——f e2 展开成 echo 后,e2 不做别名检查,按字面作为参数,输出 e2。

💡 要点:值尾空格是让"别名 A 的参数位置也能接别名 B"的唯一开关,适合构造 alias ll='ls -alF ' 这类"前缀别名";日常若发现"别名后面的词偶尔被意外展开",先检查前一个别名值是不是带了尾随空格。

3.11 别名值的引号嵌套与多条命令

别名值可以包含引号、分号等 shell 元字符。定义时的引号层级:外层引号保护整个 value,内层引号成为 value 的一部分,在调用展开后生效:

$ alias sayit="echo 'single-quoted words'"

$ sayit
single-quoted words

$ alias myls='ls -l --color=auto'

$ myls /root/demo/alias
total 8
-rw-r--r-- 1 root root 11 Oct 15 21:15 a.txt
-rw-r--r-- 1 root root 12 Oct 15 21:15 b.txt

$ alias two='echo first-part; echo second-part'

$ two
first-part
second-part

说明与解读:

  • sayit 用双引号包外层、单引号包内层——展开后执行 echo 'single-quoted words',单引号让 single-quoted words 作为一整个词;
  • 反过来若 value 内部需要双引号,外层就用单引号:alias x='echo "double quoted"';两层引号交替嵌套即可;
  • two 的值含分号,展开后按两条命令依次执行,输出 first-part、second-part;
  • myls 追加了路径参数,展开成 ls -l --color=auto /root/demo/alias,参数接在别名值之后(对照 3.7 节:别名值之后的词原样保留)。

💡 要点:value 里出现 $、反引号时务必用单引号包外层(禁止定义时展开),例如 alias today='echo $(date +%F)'——若用双引号包外层,$(date +%F) 会在定义那一刻就执行固定下来,别名永远返回同一天。

3.12 配套命令 unalias:删除别名(单个 / 批量 / -a 全清)

unalias 按名字删除别名,支持一次删多个;-a 删除当前会话全部别名。删除后调用该名字会得到 command not found(rc=127):

$ unalias st

$ st
/root/alias-test.sh: line 3: st: command not found

$ unalias gs

删除不存在的别名同样报 not found,退出码为 1:

$ unalias nosuchalias; echo rc=$?
/root/alias-test.sh: line 3: unalias: nosuchalias: not found
rc=1

一次删除多个与全量清空:

$ alias x1='echo one'

$ alias x2='echo two'

$ alias
alias b='ls /root/demo/alias'
alias q='echo quick'
alias x1='echo one'
alias x2='echo two'

$ unalias -a

$ alias; echo rc=$?
rc=0

unalias -a 之后 alias 输出为空,退出码仍为 0(列表为空不算错误)。删除多个别名直接罗列名字,如本组实测中的 unalias a c、unalias d f e2、unalias sayit myls。

💡 要点:① unalias -a 只清空"当前会话"的别名,不触碰 .bashrc——新开终端后 .bashrc 里的别名照常回来;② 它也不会关闭 expand_aliases 选项,清空后新定义的别名照常可用(3.11 节实测即在 unalias -a 之后进行);③ rc=1 可用于脚本判断别名是否存在。

四、实战示例

4.1 临时绕过别名:反斜杠与 command

"同名加参"别名会改变命令行为,临时想用"原始命令"时,在命令前加反斜杠 \ 或用 command 前缀,都能跳过别名展开。实测(沿用 4.1 前已定义的 alias df='df -h',演示完即删除):

$ alias df='df -h'

$ df /root/demo
Filesystem      Size  Used Avail Use% Mounted on
overlay         786G  433G  318G  58% /

$ \df /root/demo
Filesystem     1K-blocks      Used Available Use% Mounted on
overlay        824057128 454015120 333352572  58% /

$ command df /root/demo
Filesystem     1K-blocks      Used Available Use% Mounted on
overlay        824057128 454015120 333352572  58% /

$ unalias df

解读:

  • 走别名的 df /root/demo 展开为 df -h /root/demo,容量列是 Size(人类可读单位);
  • \df 与 command df 都绕过别名,直接执行真实 df,容量列变回 1K-blocks(1K 块计数);
  • 输出中的文件系统类型(如 overlay)取决于实际环境——实验机根分区为 overlay 存储;读者在物理机/云主机上会看到 ext4/xfs 等类型,两列数值形态一致即可对照。

💡 要点:\命令 是最快的"原样执行"方式(bash 规定反斜杠转义后的词不做别名检查);command 前缀还能穿透同名函数,比反斜杠更彻底。排查"命令行为与预期不符"时,第一步就是加 \ 对比一次。

4.2 防误删别名:alias rm='rm -i'

给危险命令追加确认参数是别名的第二个经典应用。定义后用 alias rm 核对生效值:

$ alias rm='rm -i'

$ alias rm
alias rm='rm -i'

之后在交互终端里每次 rm 文件 都会展开成 rm -i 文件,逐个文件询问确认。测试删除演示文件时用 -f 显式跳过确认(-f 优先级高于 -i,脚本中常用):

$ touch /root/demo/alias/tmp-safe.txt

$ rm -f /root/demo/alias/tmp-safe.txt

$ ls /root/demo/alias
a.txt
b.txt

💡 要点:① rm -i 的交互确认只在有终端输入时可用,脚本/cron 里应使用 rm -f 或精确路径;② 这类保护别名只对"手敲命令"有效,不是安全边界——\rm、command rm、脚本中的 rm 都不受影响。

4.3 别名持久化:写入 /root/.bashrc 与系统自带别名解读

别名只活在当前会话,重启终端即消失;持久化的标准做法是写入 /root/.bashrc(对 root 用户而言;普通用户写自己的 ~/.bashrc)。Ubuntu 22.04 的 /root/.bashrc 自带一组 ls 系列别名(81~83 行):

$ grep -n 'alias ll' /root/.bashrc
81:alias ll='ls -alF'

$ grep -n 'alias la' /root/.bashrc
82:alias la='ls -A'

$ grep -n 'alias l=' /root/.bashrc
83:alias l='ls -CF'

逐条解读系统自带别名:

  • ll = ls -alF:长格式 + 显示全部(含 . 开头隐藏文件)+ 文件类型符号(/ 目录、* 可执行、@ 链接等);
  • la = ls -A:显示除 . 和 .. 之外的全部文件(短格式);
  • l = ls -CF:分栏短格式 + 类型符号;
  • 加上 3.1 节 bash -ic 'alias' 列出的 grep/egrep/fgrep/ls 四条 --color=auto 别名(同在 .bashrc 中,用于非终端下的彩色输出兼容)。

自定义别名的持久化流程实测:追加一行 → 立即验证 → 删除恢复(演示后清理,避免残留):

$ cp /root/.bashrc /root/.bashrc.alias-bak

$ echo "alias dtest='echo demo-alias-from-bashrc'" >> /root/.bashrc

$ tail -1 /root/.bashrc
alias dtest='echo demo-alias-from-bashrc'

$ bash -ic 'dtest' 2>/dev/null
demo-alias-from-bashrc

$ sed -i '/alias dtest=/d' /root/.bashrc

$ bash -ic 'alias dtest' 2>/dev/null; echo rc=$?
rc=1

$ mv /root/.bashrc.alias-bak /root/.bashrc

流程解读:

  • echo "alias dtest='...' >> /root/.bashrc" 把别名追加到文件末尾(外层双引号保护内层单引号,写法与 3.11 节一致);
  • bash -ic 'dtest' 模拟"新开一个交互 shell",加载 .bashrc 后 dtest 立即可用,输出 demo-alias-from-bashrc(2>/dev/null 丢弃该场景下的作业控制提示,见 3.1 节);
  • sed -i '/alias dtest=/d' 删除该行后,新 shell 中 alias dtest 返回 rc=1,证明持久化来源就是 .bashrc 这一行;
  • 对已打开的当前终端,追加后需要 source ~/.bashrc 才生效(呼应 3.6 节时机规则)。

4.4 一套可直接抄走的个人别名清单

组合前文实测过的写法(同名加参、引号嵌套、多命令),给出一套常用个人别名。每一条的语法形态都在本文实测验证过:

# 追加默认参数型(自引用防递归,见 3.9 节)
alias df='df -h'
alias du='du -h'
alias grep='grep --color=auto'

# 防误删型(见 4.2 节)
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# 换名+组合命令型(见 3.4 / 3.11 节)
alias gs='git status'
alias ports='ss -tulanp'
alias today='echo $(date +%F)'

写入 .bashrc 后 source ~/.bashrc 生效;带参数的需求(如 greet_fn)改用函数实现,对照 3.7 节的选型表。

⚠️ 注意:today 这类含 $(...) 的别名必须用单引号定义——本节清单全部使用单引号,读者直接整段复制即可;若手滑改成双引号,today 会在定义那一刻被展开成固定日期(机制见 3.11 节要点)。

五、注意事项与常见问题

Q1:定义了别名,为什么 alias 列表里没有 / 调用报 command not found? 三个最常见原因,对应三节实测:① 在同一行定义后立即调用——别名按"读取整行"时机展开,该行读入时别名尚不存在(3.6 节,rc=127);② 在非交互 shell(脚本、cron、bash file.sh)中使用且未开启 shopt -s expand_aliases(3.4 节);③ 别名定义在 .bashrc 里但当前会话没有重新 source——source ~/.bashrc 或重开终端(4.3 节)。

Q2:别名里写了 $1,为什么取到的是别的值而不是我传的参数? 别名是纯文本替换,没有参数槽位。alias greet='echo hello $1' 调用 greet world 时,world 只是拼在展开文本后面的词,$1 展开的是当前 shell 自身的位置参数(3.7 节实测输出 hello TOPLEVEL-ARG world)。需要参数请改用函数:greet_fn() { echo "hello $1"; }(3.7 节实测)。

Q3:别名在脚本 / cron 里不生效,交互终端却正常,为什么? bash 默认只在交互 shell 中展开别名。脚本里需要两步:先 shopt -s expand_aliases,再定义(且定义行与调用行必须分行,见 Q1-①)。cron 默认 shell 为 sh 且非交互,别名基本不可用——cron 任务里应写完整命令路径。3.1 节的空列表与 4.3 节 bash -ic 的对照就是这一差异的实测证据。

Q4:别名 A 的值是别名 B,会不会无限递归展开? 不会。bash 对展开文本的首词持续做别名检查(a='b'、b='ls ...' 时 a 能一路展开到 ls,3.8 节实测),但与正在展开的别名同名的词不再展开——所以 alias df='df -h' 安全(3.9 节),alias loop='loop' 调用时得到 command not found(3.8 节,rc=127)而非死循环。

Q5:alias、function、脚本三者同名时,bash 先用哪个?如何排查? 查找优先级为:别名 → 函数 → 内置命令 → 外部命令。排查用 type -a name,它会按优先级列出所有同名命中。本文实测 type alias 输出 alias is a shell builtin(一、环境信息),读者可用 type -a ls 观察自己的 ls 同时命中别名与外部命令。选型参考 3.7 节拓展表:换名加参用别名,带参数用函数,要复用写脚本。

Q6:unalias -a 会把 expand_aliases 开关也关掉吗?新定义的别名还能用吗? 不会、能用。unalias -a 只清空别名表(数据),不动 shopt 选项(开关)。3.12 节实测全清后,3.11 节在同样的脚本会话里继续 shopt -s expand_aliases 并定义 sayit、myls,调用均正常。另外全清后 alias 返回 rc=0(空列表不是错误)。

Q7:别名能传给子进程 / 子 shell 吗? 不能。别名不属于环境变量,不随进程传递;子 shell(如 bash -c '...')里看不到父会话的别名。需要跨进程复用逻辑时:轻量用 export -f 函数名(函数可经环境传给子 bash),通用做法是写成脚本放入 PATH。这也是别名与 export 的本质区别——见同系列《export 命令详解与参数实测(Ubuntu 22.04)》。

六、参考链接