我试图递归地查找文件夹中的所有目录,同时通过排除所有包含.git
文件的路径来排除所有 git 子模块。我怎样才能做到呢?
解释:
.git
文件存在于每个子模块文件夹的根目录中。该子模块文件夹可以包含在任何地方。
测试用例
$ mkdir Test
$ cd Test
$ mkdir a
$ mkdir b
$ mkdir c
$ cd a
$ mkdir .git
$ cd ..
$ cd b
$ touch .git
$ cd ..
$ cd c
$ mkdir c1
$ mkdir c2
$ cd..
$ find . -type d \( \( ! -name . -exec [ -e {}/.git ] \; -prune \) -o \( \( \
-name .git\
-o -name .vscode\
-o -name node_modules\
-o -name Image\
-o -name Rendered\
-o -name iNotebook\
-o -name GeneratedTest\
-o -name GeneratedOutput\
\) -prune \) -o -print \) | sort
预期成绩
.
./a
./c
./c/c1
./c/c2
答案1
find
操作也是测试,因此您可以使用以下命令添加测试-exec
:
find . \( -exec [ -f {}/.git ] \; -prune \) -o \( -name .git -prune \) -o -print
这适用于三组操作:
-exec [ -f {}/.git ] \; -prune
修剪包含名为的文件的目录.git
-name .git -prune
修剪指定的目录.git
(因此该命令不会在.git
存储库的主目录内搜索)-print
打印上面未捕获的任何内容。
要仅匹配目录,请-type d
在 之前添加-print
,或者(以节省处理文件的时间):
find . -type d \( \( -exec [ -f {}/.git ] \; -prune \) -o \( -name .git -prune \) -o -print \)
.
通过更改find
启动路径,在除 之外的目录上运行此命令时,这也适用:
find /some/other/path -type d \( \( -exec [ -f {}/.git ] \; -prune \) -o \( -name .git -prune \) -o -print \)
答案2
我们可以创建一个递归find
:
将以下行添加到脚本文件中:
#!/bin/bash
if [ ! -f "$1"/.git ]; then
echo "$1"
find "$1" -mindepth 1 -type d -prune -exec "$0" {} \;
fi
我命名了该文件findifnotgit
,但这并不重要。然后使其可执行
chmod u+x findifnotgit
然后使用您想要运行的路径作为参数运行它:
./findifnotgit .
-->.
对于当前目录
或者
./findifnotgit /path/to/search/
解释:
if [ ! -f "$1"/.git ]; then ... fi
.git
仅当当前文件夹中没有文件时才运行以下命令($1
)- 我们需要
-mindepth 1
选项让 find 找不到我们开始的文件夹,这会创建无限循环。 - 我们需要
-prune
让 find 不会下降到目录中。我们会在里面自己做这件事-exec
。 -exec "$0" {}
$0
将使用发现的内容调用相同的脚本。
答案3
以下是如何告诉 find 不要查看 .git 或 .hg 存储库内部。
find . \( -iname '.git' -o -iname '.hg' \) -prune -false -o -iname '*thing-i-am-looking for*'
答案4
有点脏脚本,但这会找到所有不包含文件的目录.git
:
#!/bin/bash
# find dirs that contain *.git files and store in array
exclude_dirs=($(find . -type f -iname ".git" | xargs -i dirname {}))
# set up the base command
command="find . -type d"
# loop over each element in array by index
for i in $(seq 0 $(expr ${#exclude_dirs[@]} - 1)); do
command="${command} -not -path ${exclude_dirs[$i]}"
done
# run the find
eval ${command}
编辑:
修复了语法错误并更新*.git
为.git
编辑2:
是的,那是错的,我很抱歉。已编辑,现在它实际上可以工作了。