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


11

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

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脚本中完全相同的行不起作用。

Answers:


11

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

## 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

这是我第二次找到此答案(是的,记忆不佳)。这次尝试env > file1在脚本中先运行run ./it,然后再执行env > file2source it,以希望我发现envs 有所不同,但事实并非如此。如何以编程方式列出两个外壳之间的所有差异(在这种情况下为交互式与非交互式)?
Enrico Maria De Angelis


2

在脚本顶部附近添加以下行:

shopt -s extglob

!(...)是扩展的模式匹配功能,需要extglob启用选项才能使用它。有关更多详细信息,请参见内置shopt

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.