【问题标题】:bash discard/edit part of glob (script fails when part of glob not found)bash 丢弃/编辑 glob 的一部分(当找不到 glob 的一部分时脚本失败)
【发布时间】:2015-06-09 03:19:40
【问题描述】:

我正在用 BASH 编写一个脚本,它基本上就像一个简化的 gmake 和包构建器。它只支持一种语言;这是设计使然。我不打算发布此脚本,因为它仅供本地使用。

我基本上已经让它正常工作了。在更复杂的项目上,它处理得很好。在做一个简单的测试程序时出现了一个问题。

脚本将«args» 构建为具有基本参数的合理默认值。无论“模式”如何,脚本始终执行以下形式的一行:

«compiler» «args» *.«ext»

鉴于支持的语言 (Ada) 有两个文件扩展名,以下 glob 用于编译为 «ext»:

*.{ads,adb}

当两个扩展都存在时,正如在大型项目中所预期的那样,一切都很好。但是当 $PWD 中只存在一个扩展时,脚本会失败,并且不会进行编译。

我对此感到很困惑,因为存在“干净模式”,它就是这样做的:

rm *.{ali,o,so}

即使 $PWD 中不存在某些列出的扩展名,这也有效。

我可以调用编译器两次,首先传递一个扩展名(如果存在相应的文件),然后同样传递另一个扩展名。但是,这会导致对许多文件进行两次编译,这显然是低效的。

我认为可以在脚本的早期构建 $PWD 中存在哪些扩展的 glob,然后将 glob 传递给编译器。但是,我完全不知道如何做到这一点。一些尝试让 bash 抱怨找不到命令“*.{adb,ads}”。这真的让我大吃一惊,因为我基本上只是在做:

«compiler» «args» $FoundFiles

【问题讨论】:

    标签: bash shell glob


    【解决方案1】:

    使用nullglob:

    shopt -s nullglob
    compiler other_args *.{ads,adb}
    

    说明

    让我们使用一个有一个 .ads 文件但没有 .adb 文件的目录:

    $ echo *.{ads,adb}
    1.ads *.adb
    

    默认情况下,如果没有文件匹配 glob,bash 将返回 glob 本身,在本例中为 *.adbnullglob 选项改变了这一点,没有匹配的 glob 将被省略。因此:

    $ shopt -s nullglob
    $ echo *.{ads,adb}
    1.ads
    

    要将 nullglob 重置为关闭,请使用:

    shopt -u nullglob
    

    【讨论】:

      【解决方案2】:

      大括号扩展将*.{adb,ads} 变成两个词,*.adb*.ads。然后,它们中的每一个都(独立地)全局扩展。如果 glob-expansion 失败,则 glob 会不加修改地传递,而不是被删除。例如,如果您没有扩展名为 ads 的文件,您最终可能会尝试编译 f1.adb f2.adb *.ads。由于最后一个不存在,编译器会报错。

      rm *.{ali,o,so}rm 会发生完全相同的事情,如果其中一种模式未经修改通过,则会抱怨并停止。但如果该命令真的是rm -f *.{ali,o,so},那么它将执行得很好,因为-f 标志告诉rm 忽略丢失的文件(除其他外)。

      您可以通过设置nullglob shell 选项 (shopt -s nullglob) 来修改 bash 对不匹配 glob 的处理;设置该选项后,不匹配的 glob 将从单词列表中删除,而不是未经修改地通过。

      但是,在这种特殊情况下,您也可以使用

      compile *.ad[bs]
      

      它是一个单一的 glob,与大括号扩展的 glob 对具有相同的匹配项。如果它不匹配任何内容,这也将通过未修改的方式传递,但这意味着根本没有 Ada 文件,这应该会触发错误消息。设置nullglob 后,最终结果将是调用不带参数的编译器;这也可能会产生错误消息,但如果没有提供任何参数,某些实用程序将处理标准输入,在这种情况下您必须小心nullglob

      【讨论】:

      • 阅读整个 BASH 手册,一定错过了括号球。
      猜你喜欢
      • 2020-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 2016-06-24
      • 1970-01-01
      相关资源
      最近更新 更多