AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 478813
Accepted
user938271
user938271
Asked: 2018-10-31 20:19:47 +0800 CST2018-10-31 20:19:47 +0800 CST 2018-10-31 20:19:47 +0800 CST

为什么文件名生成失败会使 zsh 停止处理脚本?

  • 772

我试图编写一个简短的脚本来编写在以下位置找到的所有可执行程序$PATH:

for dir in $(tr ':' ' ' <<<"${PATH}"); do
  for pgm in $dir/*; do
    if command -v "${pgm}" >/dev/null 2>&1; then
      echo "${pgm}"
    fi
  done
done | sort >file

在 bash 中,它按预期工作,但一旦文件名生成在内部循环中失败,zsh 就会停止处理脚本:

for pgm in $dir/*; do
           ^^^^^^
  ...
done

结果,由于 my$PATH包含一个不包含任何文件 ( /usr/local/sbin) 的目录,因此在 zsh 中,脚本无法写入随后在目录中找到的可执行文件。

这是显示相同问题的另一个代码:

for f in /not_a_dir/*; do
  echo 'in the loop'
done
echo 'after the loop'

在 bash 中,此命令输出:

in the loop
after the loop

并退出代码0。

在 zsh 中,相同的命令输出:

no matches found: /not_a_dir/*

并退出代码1。

shell 之间的行为差​​异似乎来自nomatch选项,该选项在man zshoptions:

NOMATCH (+3) <C> <Z>

如果用于文件名生成的模式没有匹配项,则打印错误,而不是在参数列表中保持不变。这也适用于初始~或=.

并且还在man zshexpn(文件名生成部分)中进行了解释:

该词被替换为与模式匹配的排序文件名列表。如果没有找到匹配的模式,shell 会给出一个错误信息,除非设置了 NULL_GLOB 选项,在这种情况下这个词会被删除;或者除非未设置 NOMATCH 选项,在这种情况下,单词保持不变。

因为如果我取消设置nomatch,zsh 的行为就像 bash:

unsetopt nomatch
for f in /not_a_dir/*; do
  echo 'in the loop'
done
echo 'after the loop'

现在我了解了 bash 和 zsh 之间的行为差​​异,以及为什么脚本会在 zsh 中引发错误,但我想了解为什么文件名生成失败会使 zsh 立即停止处理脚本。因此,我尝试通过用失败的命令(通过执行not_a_cmd)替换失败的文件名生成来重现相同的问题:

for f in ~/*; do
  not_a_cmd
done
echo 'after the loop'

但是这个脚本的输出在两个 shell 中几乎是相同的(除了由于 引起的错误消息not_a_cmd)。特别是,两个 shell 都打印:

after the loop

并且两个 shell 都以代码退出0。

为什么文件名生成失败(如for f in /not_a_dir/*)会使 zsh 停止处理脚本,而不是失败的命令(如not_a_cmd)?

我正在使用zsh 5.6.2-dev-0 (x86_64-pc-linux-gnu).

zsh
  • 1 1 个回答
  • 234 Views

1 个回答

  • Voted
  1. Best Answer
    Marlon Richert
    2020-06-27T08:27:12+08:002020-06-27T08:27:12+08:00

    这是一个功能,而不是错误。?

    正如Zsh 手册中的“错误”部分所述:

    某些错误被 shell 视为致命错误:在交互式 shell 中,它们导致控制返回命令行,而在非交互式 shell 中,它们导致 shell 中止。[…]

    在非交互式 shell 中发现的致命错误包括:

    • […]
    • 选项未捕获的文件生成错误BAD_PATTERN
    • […]
    • 不是由NO_MATCH或类似选项引起的文件生成失败。

    至于背后的原因,我在 Zsh 邮件列表档案中找到了这个电子邮件交换:

    在其他 shell 中,这是以一种非常简单的方式实现的,如果可以扩展通配符,则将其扩展,否则将星号作为参数发送给应用程序。

    是的,其他 shell 也是这样做的,但这有其缺点。例如,如果您运行“touch *,c”,最好得到“不匹配”而不是创建无用的 *,c 文件。或者,如果您键入这样的命令:“rsync -avP *.html *.shmtl *.php host:/dest/”(注意拼写错误),最好立即得到“不匹配”错误,而不是得到一个单独的开放错误嵌入在所有输出中,然后您必须在传输结束时弄清楚。我更喜欢简单地将单引号放在任何不应扩展的通配符文件名周围,而不是将 shell 配置为包含一个不匹配任何内容的通配符。当然是 YMMV,但是如果您尝试一下,您可能会发现自己也开始喜欢它了。

    • 2

相关问题

  • 列出没有其他后缀文件的文件

  • 什么情况下路径中最先找到的可执行文件不会被使用

  • 符号链接所有点文件和目录

  • 如何在`zsh`中增加一个动态命名的变量

  • 为什么我不能在 zsh 中定义一个名为 path 的只读变量?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve