括号在 bash shell 本身中有效,但在 bash 脚本中无效

括号在 bash shell 本身中有效,但在 bash 脚本中无效

我可以从命令行提示符运行此命令:

cp -r folder/!(exclude-me) ./

递归复制所有内容folder 除了exclude-me为当前目录中命名的子目录。这完全按照预期工作。但是,我需要它在我编写的 bash 脚本中工作,其中我有以下内容:

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./
  rm -rf folder
fi

但是当我运行脚本时:

bash my-script.sh

我明白了:

my-script.sh: line 30: syntax error near unexpected token `('
my-script.sh: line 30: `  cp -r folder/!(exclude-me) ./'

我不知道为什么它可以在命令提示符下工作,但完全相同的行在 bash 脚本中不起作用。

答案1

这是因为您使用的语法取决于未激活的特定 bash 功能。您可以通过将相关命令添加到脚本中来激活它:

## Enable extended globbing features
shopt -s extglob

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./ &&
    rm -rf folder
fi

这是以下的相关部分man bash

  If the extglob shell option is enabled using the shopt builtin, several
  extended  pattern  matching operators are recognized.  In the following
  description, a pattern-list is a list of one or more patterns separated
  by a |.  Composite patterns may be formed using one or more of the fol‐
  lowing sub-patterns:

         ?(pattern-list)
                Matches zero or one occurrence of the given patterns
         *(pattern-list)
                Matches zero or more occurrences of the given patterns
         +(pattern-list)
                Matches one or more occurrences of the given patterns
         @(pattern-list)
                Matches one of the given patterns
         !(pattern-list)
                Matches anything except one of the given patterns

在您的情况下,在 bash 的交互式调用中启用它的原因可能是因为您有shopt -s extglob~/.bashrc因为您正在使用https://github.com/scop/bash-completionbash-completion至少在基于 Debian 的操作系统中的软件包中可以找到)包含 via~/.bashrc/etc/bash.bashrcwhichextglob初始化时启用

请注意,这些 ksh 风格的扩展 glob 运算符也可以在构建时通过传递--disable-extended-globconfigurebash 源代码中的脚本来完全禁用,或者使用--enable-extended-glob-default.

但请注意,这extglob违反了 POSIX 合规性。例如,虽然echo !(x)POSIXsh语言中未指定 的行为,

a='!(x)'
echo $a

需要输出!(x)假设默认值$IFS,而不是当前目录中除 之外的文件名列表,因此对于打算用作 的x构建不应执行此操作。在 ksh 中,这些运算符默认启用,但在扩展时无法识别。bashshX(...)

答案2

在脚本顶部附近添加此行:

shopt -s extglob

!(...)是一个扩展的模式匹配功能,您需要extglob选项enable才能使用它。看内置商店更多细节。

相关内容