Bash 命令中的通配符 (*) 导致捕获正确的输出

Bash wildcard (*) in command causes in correct output to be captured

请原谅标题的措辞,我不确定如何为这个标题起一个朗朗上口的标题'issue'。

如果我 运行 在我的终端中执行以下命令 (运行 MacOS Sierra 10.12.6) git branch --list [rR]elease*

它产生以下预期结果

* Release-x
  release-1
  release-2
  release-3

但是,如果我将以下内容放入 bash 脚本中

branches=($(git branch --list [rR]elease*))

for branch in "${branches[@]}"
do
  echo "Found branch $branch"
done

它似乎采用 * 并回显找到的分支以及我当前工作目录中的每个 file/directory 名称。

Found branch README.md
Found branch acceptance-test
Found branch build
Found branch build.gradle
Found branch flow.sh
Found branch gradle
Found branch gradle.properties
Found branch gradlew
Found branch gradlew.bat
Found branch performance-tests
Found branch postman
Found branch service
Found branch settings.gradle
Found branch sonar-project.properties
Found branch Release-x
Found branch release-1
Found branch release-2
Found branch release-3

为什么输出不同?目前,这打破了脚本的逻辑,因为它期望分支。如果可能的话,我想避免进行冗余检查(检查这是否是一个实际的分支)使脚本混乱。

编辑:我试过引用 * 并且它产生与上面相同的结果。

Visual version of the problem

$(git...) 在存储到您的数组之前会进行路径名扩展。 * branchname 标记 git 中的当前分支。当构造数组 branches 时,git 命令输出中的 * 扩展为当前目录中的所有文件。

您可以使用 set -f 关闭路径名扩展。此外,您必须将 $IFS 设置为 <newline>,否则带有空格的行将被拆分为更多项(*<space>branchname 将变为 *branchname ):

old_IFS=$IFS
IFS=$'\n'   
set -f
branches=($(git branch --list '[rR]elease*'))    
set +f   
IFS=$old_IFS

或者更好的方法是使用 readarray:

readarray -t branches < <(git branch --list '[rR]elease*')

或者您可以将 while 循环与 read 结合使用。这也将 trim 前导空格。如果不需要,请使用 IFS= read -r ...:

branches=()
while read -r branch; do
    branches+=("$branch")
done < <(git branch --list '[rR]elease*')