在bash脚本中处理git命令数组

时间:2018-12-26 17:33:21

标签: bash git

所有人的祝福:

我正在编写一个bash脚本以从git repos中提取数据。我有一个数组来存储存储库名称:

declare -a arr=(
https://"$USER"@stash/repo1.git
https://"$USER"@stash/rep2.git
)

我按以下方式处理它:

for i in "${arr[@]}"
do
    git clone "$i"
    ......
    git install
done

这有效。现在,我希望能够有选择地指定一个git分支:

declare -a arr=(
    -b branch1 --single-branch https://"$USER"@stash/repo1.git
    https://"$USER"@stash/rep2.git
)

数组处理脚本失败,出现多个难看的错误: -开关“ b”需要一个值 -无效的标识符等

什么是使它正常工作的正确且简单的方法?

2 个答案:

答案 0 :(得分:1)

c.f。 printf "%s\n" "${arr[@]}"。仅仅因为这些args在一行上并不能使它们成为一个元素。 :)

您试图用一个数组做两件事。

尝试一下-

declare -a arr=(
   "https://$USER@stash/repo1.git#branch1"
   "https://$USER@stash/rep2.git"
)

for i in "${arr[@]}"
do  IFS='#' read url branch <<< "$i"
    if [[ -n "$branch" ]]
    then git clone -b "$branch" --single-branch "$url"
    else git clone "$url"
    :    ......
    git install
done

警告-没有机会进行测试。 Caveat Scriptor -当然,这意味着#不能出现在您的url中。

答案 1 :(得分:0)

如果删除引号

也许会有用
git clone "$i"

所以它看起来像这样:

git clone $i

我认为带引号的shell应该将所有行都视为一个参数,而不是多个参数。

git clone "-b branch1 --single-branch https://"$USER"@stash/repo1.git"

这看起来不对。

编辑: @CharlesDuffy指出了我遗漏的另一个问题:您还应该在数组定义的整行周围都加上引号(但是如果您确实需要在$USER周围加上内部引号,则此方法将无效,请参见下面的示例):

declare -a arr=(
    "-b branch1 --single-branch https://$USER@stash/repo1.git"
    https://"$USER"@stash/rep2.git
)

我在本地计算机上检查了这一点,它似乎可以正常工作。

$ ls
one/  test.sh*

$ ( cd one/ ; git branch )
* another_branch
  master

$ cat test.sh
#!/bin/bash

declare -a arr=(
"-b another_branch --single-branch one two"
)

for i in "${arr[@]}"
do
        git clone $i
done

$ ls
one/  test.sh*

$ ./test.sh
Cloning into 'two'...
done.

$ ls
one/  test.sh*  two/

$ ( cd two/ ; git branch )
* another_branch

$

EDIT2: 只有在您可以安全地省略$USER周围的内部引号的情况下,这才起作用。如果需要它们,则应在for循环内使用eval,并在数组声明中引用内部引号。

$ cat ./test.sh
#!/bin/bash

USER="username containing spaces"   # just for example!

git () {
        echo "$5"
}

declare -a arr=(
"-b branch1 --single-branch https://\"$USER\"@stash/repo1.git"
)

for i in "${arr[@]}"
do
        printf "without eval:\t"
        git clone $i
        printf "with eval:\t"
        eval "git clone $i"
done


$ ./test.sh
without eval:   https://"username
with eval:      https://username containing spaces@stash/repo1.git

这是@CharlesDuffy在我的答案中发现的另一个错误。谢谢查尔斯,我从更深入地了解您指出的问题中学到了很多东西!