虽然zsh 文档(ch 6.2)提供了预命令修饰符可以执行的操作的描述,但它未能提供每种类型的示例:-
、builtin
、command
、exec
、nocorrect
和noglob
。
用户Tuyen Pham也提出了类似的问题。但是,该问题并不强调为每种类型的预命令修饰符请求示例。
任何人都可以提供每个预命令修饰符可以做什么的示例吗?
干杯!
请注意,我为下面的每个修饰符给出了一个示例。除了此处显示的用途之外,有些(例如exec
和)还有多种用途。command
用于-
运行实用程序将插入破折号作为其第零个参数(命令名称)的第一个字符。破折号作为命令名称的第一个字符是向 shell 发出信号的常用方法,表明它应该初始化为登录 shell。
# Start the yash shell as a login shell:
- yash
Run Code Online (Sandbox Code Playgroud)
这可能会使您启动的 shell 读取一组不同的启动脚本。例如,在 的情况下yash
,它将首先读取~/.yash_profile
文件,否则它不会这样做。
当 shell 以-
的第一个字符启动时$0
,它将是一个登录 shell。登录 shell 通常也会有一个l
(小写的 ell)$-
(尽管bash
shell 似乎不遵循这个习惯):
$ sh -c 'echo "$0"; echo "$-"'
sh
ch
Run Code Online (Sandbox Code Playgroud)
$ - sh -c 'echo "$0"; echo "$-"'
-sh
clh
Run Code Online (Sandbox Code Playgroud)
使用builtin
,您可以确保您运行的命令是该命令的内置变体,而不是外部命令、别名或 shell 函数:
builtin cd mydir
Run Code Online (Sandbox Code Playgroud)
例如,如果您想要编写一个名为 的 shell 函数cd
,作为其功能的一部分,称为 的内置变体cd
来实际更改工作目录,这可能会很有用。使用 justcd
会导致对函数的递归调用。
$ cd () { builtin cd "$@" && printf 'Now in %s\n' $PWD; }
$ cd /tmp
Now in /tmp
Run Code Online (Sandbox Code Playgroud)
该command
命令是标准 POSIX 命令,例如,可用于确定用户当前的系统上是否存在特定实用程序PATH
:
if ! command -v gsed >/dev/null 2>&1; then
echo 'gsed is not available'
fi
Run Code Online (Sandbox Code Playgroud)
该command
命令通常还用于禁用给定实用程序的别名和函数查找,其方式与我builtin
上面展示的类似。
该exec
关键字也是standard,可用于将当前 shell完全替换为另一个进程:
# Replace the shell with bash
exec bash
Run Code Online (Sandbox Code Playgroud)
此后键入exit
不会返回到原始 shell 会话,因为它已被bash
shell 会话替换。
您还可以用来exec
为当前 shell 的标准 I/O 流设置重定向。
如果当前交互式 shell 会话启用了拼写校正 ( setopt CORRECT
),则使用nocorrect
将不会启用该命令的校正。
按说:
$ setopt CORRECT
$ seed
zsh: correct 'seed' to 'sed' [nyae]? n
zsh: command not found: seed
Run Code Online (Sandbox Code Playgroud)
和nocorrect
:
$ setopt CORRECT
$ nocorrect seed
zsh: command not found: seed
Run Code Online (Sandbox Code Playgroud)
该noglob
修饰符禁用当前命令的通配符:
$ noglob echo *
*
Run Code Online (Sandbox Code Playgroud)
如果没有noglob
修饰符,*
模式将被扩展,并且生成的单词(当前目录中的文件名)将作为参数给出echo
。
在其他 shell 中,可以使用 暂时关闭通配符set -f
,然后使用 再次打开它set +f
。这将是在 shell 中禁用文件名通配的标准方法。该set -f
命令不会影响 中的通配zsh
,除非 shell 正在模拟sh
或ksh
。