括号适用于 bash shell 本身,但不适用于 bash 脚本

nzi*_*nab 13 bash shell-script

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

cp -r folder/!(exclude-me) ./
Run Code Online (Sandbox Code Playgroud)

递归复制folder 指定子目录外的所有内容exclude-me到当前目录中。这完全按预期工作。但是,我需要它在我编写的 bash 脚本中工作,我有这个:

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

但是当我运行脚本时:

bash my-script.sh
Run Code Online (Sandbox Code Playgroud)

我明白了:

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

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

ter*_*don 15

这是因为您使用的语法取决于特定的 bash 功能,对于非交互式 shell(脚本),默认情况下该功能未激活。您可以通过在脚本中添加相关命令来激活它:

## Enable extended globbing features
shopt -s extglob

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

这是的相关部分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
Run Code Online (Sandbox Code Playgroud)