我只是不明白,为什么我不能做我刚才在问题中提到的事情?
为进一步说明,我试图遍历某个路径中的所有目录,该目录存储在我选择的任何随机变量中。请查看下面的脚本,让我知道为什么在运行脚本时为什么执行没有经过for
循环开始语句:
gpll_allrepos3() {
export SIMPROJS="/c/Projects/mainproject"
currPath=$(pwd)
for repoFolder in $SIMPROJS; do
echo "RepoFolder: $repoFolder"
if [[ -d "$SIMPROJS/$repoFolder/.git" && ! -L "$SIMPROJS/$repoFolder/.git" ]]; then
echo "$SIMPROJS/$repoFolder"
cd "$SIMPROJS/$repoFolder" && echo "Now inside $SIMPROJS/$repoFolder"
curr_branch=$(git rev-parse --abbrev-ref HEAD)
## git pull && git pull origin
## if [[ "$curr_branch" != "master" ]]; then
### Merging master branch as the current branch is feature branch
git checkout master
git pull && git pull origin
git checkout $curr_branch
git merge master
## fi
fi
done
cd $currPath
}
gpll_allrepos3
我不是一个非常出色的Bash脚本编写者,因此可以提出任何建议,但请注意,我需要能够从我选择的任何位置运行此脚本。
答案 0 :(得分:1)
for
不会遍历目录的内容,而是遍历一系列“单词”(基本上是字符串)。因此,此语句:
for var in alice bob "jimmy joe" /c/Projects/mainproject; do
...将运行其内容四次,首先将var
设置为“ alice”,然后将其设置为“ bob”,然后将其设置为“ jimmy joe”,然后将其设置为“ / c / Projects / mainproject”。它不会将其中任何一个视为文件名或目录名,因为您没有要求这样做。另一方面,shell将/c/Projects/mainproject/*
扩展到目录/ c / Projects / mainproject /中的文件列表(包括路径前缀)。因此,您可以使用:
for repoFolder in "$SIMPROJS"/*; do
通配符字符串将扩展为一系列单词(对应于/ c / Projects / mainproject /下的文件和目录),然后for
将遍历这些单词。
注意变量引用周围的双引号吗?这样做总是一个好主意,否则shell会根据空格(或IFS
变量中的内容)将变量的内容拆分为多个单独的单词,并在变量的值中扩展通配符,而您通常不这样做不要这样做(如果意外发生,可能会引起麻烦)。另一方面,*
必须在双引号的 之外,以便扩展到文件列表,而不仅仅是被视为文字文件名。
此外,请注意,这将遍历文件和/ c / Projects / mainproject中的子目录。如果只需要子目录,请使用以下命令:
for repoFolder in "$SIMPROJS"/*/; do
添加的尾部斜杠会将其限制为仅与目录匹配(因为在目录路径末尾的斜杠是有意义的,但在普通文件路径的末尾则没有意义)。但是请注意,结尾的斜杠也将包含在结果路径中。
其他说明:请勿使用"$SIMPROJS/$repoFolder"
等-repoFolder
变量已经包含路径前缀(因为它已包含在扩展的通配符字符串中),因此再次添加它会导致麻烦。只需使用"$repoFolder"
。
此外,在脚本中使用cd
时,应始终包括错误处理,以防由于某种原因而失败。否则,脚本将继续在错误的位置运行,可能会导致混乱。您使用:
cd "$SIMPROJS/$repoFolder" && echo "Now inside $SIMPROJS/$repoFolder"
...如果此操作失败(由于路径加倍问题而将失败),它将不会显示“ Now inside ...”消息,但将继续执行其他所有操作。您应该使用的更像这样:
cd "$repoFolder" || {
echo "Couldn't cd into $repoFolder, cancelling..." >&2
return 1
}
...这将退出功能,而不是盲目地在错误的位置继续执行。
BTW,shellcheck.net善于发现此类常见问题;我建议至少通过它来运行脚本,直到您对Shell脚本更加熟悉为止。
答案 1 :(得分:1)
要遍历目录中的文件,您需要提供一个可以为expanded to a filename glob的字符串。
有了它,循环变量将包含整个路径,因此无需在原始目录名称前加上前缀。
此外,您可以使用pushd
和popd
来避免创建$currPath
变量。
#!/bin/bash
simprojs="/c/Projects/mainproject"
for repoFolder in "$simprojs"/*; do
if [[ -d "$repoFolder/.git" && ! -L "$repoFolder/.git" ]]; then
pushd "$repoFolder" && echo "Now inside $repoFolder"
curr_branch=$(git rev-parse --abbrev-ref HEAD)
git checkout master
git pull && git pull origin
git checkout "$curr_branch"
git merge master
fi
done
popd
答案 2 :(得分:1)
脚本似乎已解决了问题,可以使用find
:find $SOMEPATH -type d -name .git -execdir git checkout master \; -execdir git pull && git pull origin \; -execdir ... \;
。
find
中名为“ .git”(-type d
)的 -name .git
目录($SOMEPATH
)。对于每个.git目录,从包含匹配文件(command
)的子目录中运行-execdir command \; -execdir command \; -execdir ... \;
。
您不需要{。{1}}到.git目录,也不需要维护一堆目录(例如cd
和pushd
),等等。衬垫。注意:默认情况下,popd
从不跟随符号链接(参见op的find
)。