BASH Linux-如何将find的结果传递到for循环中
我得到一个包含不同Git repo的本地目录。目录树如下所示:BASH Linux-如何将find的结果传递到for循环中,bash,sh,Bash,Sh,我得到一个包含不同Git repo的本地目录。目录树如下所示: Dir - dir1 --- repo1 - dir2 --- repo2 - dir3 --- repo3 for i in `find . -type d -name .git` do dir=`dirname $i` pushd . cd $dir git pull popd done 我想创建一个Bash脚本,它使用find命令获取所有.git目录名,然后将for循环中的所有路径传递到git pull远程
Dir
- dir1 --- repo1
- dir2 --- repo2
- dir3 --- repo3
for i in `find . -type d -name .git`
do
dir=`dirname $i`
pushd .
cd $dir
git pull
popd
done
我想创建一个Bash脚本,它使用find
命令获取所有.git
目录名,然后将for
循环中的所有路径传递到git pull
远程repo的所有更新。
因此,我可以通过运行这个bash脚本来更新所有repo
有人能给我一个提示吗?相关文档也很有用。不清楚您的所有存储库是否都位于同一目录级别,但它们似乎来自您的问题。从这个角度来看,不需要调用
find
,只需使用globbing即可
for dir in */; do ## for each dir under present
if [ -d "$dir/.git" ]; then ## does it have a .git dir?
pushd "$dir" >/dev/null 2>&1 ## if so, change to it
git pull ## update repo
popd >/dev/null 2>&1 ## change back to original dir
fi
done
有很多变化。我使用pushd
和popd
来避免解析路径或使用。
。您可以cd“$dir”
然后cd..
如果您愿意的话
如果目录不都在同一级别上,您可以使用
查找
,如果您正在寻找最短的实现,它可能会类似于:
cwd="$PWD" ## save current path
for dir in $(find . -type d -name "*\.git"); do ## loop over all with .git
dname="${dir#./}" ## trim leading './'
cd "$cwd/${dname%/.git}" && git pull ## change to and git pull
done
让我知道这是否对您更有利。不清楚您的所有存储库是否都位于同一目录级别,但它们似乎来自您的问题。从这个角度来看,不需要调用
find
,只需使用globbing即可
for dir in */; do ## for each dir under present
if [ -d "$dir/.git" ]; then ## does it have a .git dir?
pushd "$dir" >/dev/null 2>&1 ## if so, change to it
git pull ## update repo
popd >/dev/null 2>&1 ## change back to original dir
fi
done
有很多变化。我使用pushd
和popd
来避免解析路径或使用。
。您可以cd“$dir”
然后cd..
如果您愿意的话
如果目录不都在同一级别上,您可以使用
查找
,如果您正在寻找最短的实现,它可能会类似于:
cwd="$PWD" ## save current path
for dir in $(find . -type d -name "*\.git"); do ## loop over all with .git
dname="${dir#./}" ## trim leading './'
cd "$cwd/${dname%/.git}" && git pull ## change to and git pull
done
如果这样对您更有利,请告诉我。您可以这样做:
Dir
- dir1 --- repo1
- dir2 --- repo2
- dir3 --- repo3
for i in `find . -type d -name .git`
do
dir=`dirname $i`
pushd .
cd $dir
git pull
popd
done
你可以这样做:
Dir
- dir1 --- repo1
- dir2 --- repo2
- dir3 --- repo3
for i in `find . -type d -name .git`
do
dir=`dirname $i`
pushd .
cd $dir
git pull
popd
done
执行函数
find / "*.git" -type d -exec git pull {} \;
您可以使用find命令的exec函数。它作用于从find获取的结果。在上面,它将从/directory中搜索系统中的所有git目录/repo,一旦找到这些目录,它将对它们执行git拉取
希望这能解决您的问题执行功能
find / "*.git" -type d -exec git pull {} \;
您可以使用find命令的exec函数。它作用于从find获取的结果。在上面,它将从/directory中搜索系统中的所有git目录/repo,一旦找到这些目录,它将对它们执行git拉取
希望这能解决您的问题您可以强制
IFS
只包含\n
作为单词分隔符,这样您就可以执行以下操作
IFS='
' #only a new line.
for i in `find . -type d`
do
if [ -d "$i/.git" ]
then
foo_bar "$i"
fi
done
这不仅适用于bash,而且适用于标准的bourneshell(包括uptounix(tm)V7!!!)
编辑1
做得更好
find . -type d ... |\
while read dir
do
if [ -d "$i/.git" ]
then
foo_bar "$i" # or `basename "$i"` or whatever you like.
fi
done
当然,您可以使用直接访问.git
存储库
find . -type d -name .git |\
while read git_repo
do
foo_bar `dirname "$i"`
done
如果你知道所有回购协议都在这一水平之下,就这么做吧
for repo in */.git
do
repo_name=`dirname "$repo"`
foo_bar "$repo_name"
done
例如,正如你在问题中所注意到的
for repo in */.git
do
( cd `dirname "$repo"`
git pull
) # subshell it to conserve current dir in parent shell.
done
(语法与所有Bourne Shell兼容,而不是特定于bash(1)您可以强制
IFS
仅包含\n
作为单词分隔符,因此您可以执行以下操作
IFS='
' #only a new line.
for i in `find . -type d`
do
if [ -d "$i/.git" ]
then
foo_bar "$i"
fi
done
这不仅适用于bash,而且适用于标准的bourneshell(包括uptounix(tm)V7!!!)
编辑1
做得更好
find . -type d ... |\
while read dir
do
if [ -d "$i/.git" ]
then
foo_bar "$i" # or `basename "$i"` or whatever you like.
fi
done
当然,您可以使用直接访问.git
存储库
find . -type d -name .git |\
while read git_repo
do
foo_bar `dirname "$i"`
done
如果你知道所有回购协议都在这一水平之下,就这么做吧
for repo in */.git
do
repo_name=`dirname "$repo"`
foo_bar "$repo_name"
done
例如,正如你在问题中所注意到的
for repo in */.git
do
( cd `dirname "$repo"`
git pull
) # subshell it to conserve current dir in parent shell.
done
(语法与所有Bourne Shell兼容,而不是特定于bash的)我将建议一种完全不同的方法,它利用
find
运行命令的功能
cd Dir # Change to the top-level directory
find . -type d -name .git -exec \
sh -c 'for d in "$@"; do (cd "$d/.."; git pull) done' argv0 {} +
这会将目录更改为顶级目录,然后运行find
查找.git
目录。执行-exec
之后的命令,每个Git目录名将取代脚本中的{}
,而+
意味着在单个命令执行中将使用尽可能多的方便的名称。执行的命令是:
sh -c 'for d in "$@"; do (cd "$d/.." && git pull) done' argv0 dir1/.git dir2/.git …
argv0
参数是通过-c'…'
运行的shell脚本的$0
-如果愿意,可以使用诸如git multi-pull
之类的名称。该脚本依次处理每个参数,并通过(cd“$d/。”&&git pull)
小心地保留空格,它将目录更改为存储库的顶级目录并运行git pull
。(…)
在子shell中运行操作,这意味着如果出现问题(很难看出问题是什么,但只是以防万一),只有一个子shell会受到影响。无需尝试返回下一张cd
的正确位置-前一个子shell退出,而不会影响sh-c'…'
shell。这样做的好处是,文件名中的所有偏心字符都是自动和完全处理的
这是“在命令行中键入”版本。您可以通过删除cd Dir
并在find
命令中将
替换为“${@:-.}”
将其制作成脚本。然后,将要搜索Git repos的一个或多个目录指定为命令行参数,如果没有命令行参数,则使用当前目录
您可以在shell脚本中添加pwd
或echo“$d”
,以便在运行时回显目录名称,从而跟踪进度。如果需要,您可以演示argv0
是$0
,包括:
sh -c 'for d in "$@"; do (cd "$d/.." && echo "$0: $PWD" && git pull) done' git-multi-pull {} +
如果您喜欢神秘的shell脚本,可以省略“$@”中的;当您为d编写时,它是隐含的;do(…)done
。还要注意,当循环的整个主体是一个子shell时,在done
之前不需要分号;)
就足够了