关于 zsh 中的预命令修饰符

Mae*_*tro 2 zsh shell-builtin

背景

虽然zsh 文档(ch 6.2)提供了预命令修饰符可以执行的操作的描述,但它未能提供每种类型的示例:-builtincommandexecnocorrectnoglob

用户Tuyen Pham也提出了类似的问题。但是,该问题并不强调为每种类型的预命令修饰符请求示例。


问题

任何人都可以提供每个预命令修饰符可以做什么的示例吗?

干杯!

Kus*_*nda 6

请注意,我为下面的每个修饰符给出了一个示例。除了此处显示的用途之外,有些(例如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)$-(尽管bashshell 似乎不遵循这个习惯):

    $ 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 会话,因为它已被bashshell 会话替换。

    您还可以用来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 正在模拟shksh