Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
BASH Linux-如何将find的结果传递到for循环中_Bash_Sh - Fatal编程技术网

BASH Linux-如何将find的结果传递到for循环中

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远程

我得到一个包含不同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
远程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
之前不需要分号;
就足够了