括号适用于 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)