使用 find 获取所有没有 .git 子文件夹的文件夹

Use find to get all folders that don't have a .git subfolder

如何使用查找来获取所有没有 .git 文件夹的文件夹?

在这个结构上::

$ tree -a -d -L 2
.
├── a
│   └── .git
├── b
│   ├── b1
│   └── b2
├── c
└── d
    └── .git
        ├── lkdj
        └── qsdqdf

这个::

$ find . -name ".git"  -prune -o -type d -print
.
./a
./b
./b/b1
./b/b2
./c
./d
$

获取除 .git

之外的所有文件夹

我想要这个::

$ find . ...
.
./b
./b/b1
./b/b2
./c
$

它的效率很低(运行是一堆子进程),但下面的代码可以用 GNU 或现代 BSD 完成 find:

find . -type d -exec test -d '{}/.git' ';' -prune -o -type d -print

如果您不能保证 find 具有 POSIX 标准中未保证的任何功能,那么您可能需要承担更多的效率损失(使 {} 它自己的标记,而不是子字符串,通过 shell 运行 测试):

find . -type d -exec sh -c 'test -d "/.git"' _ '{}' ';' -prune -o -type d -print

这通过使用 -exec 作为谓词来工作,运行ning 一个 find 不支持内置的测试。

注意使用低效的 -exec [...] {} [...] \; 而不是更有效的 -exec [...] {} +;由于后者将多个文件名传递给每次调用,它无法取回每个文件名的单个结果,因此始终评估为真。

如果您不介意使用临时文件,那么:

find . -type d -print > all_dirs
fgrep -vxf <(grep '/\.git$' all_dirs | sed 's#/\.git$##') all_dirs | grep -vE '/\.git$|/\.git/'
rm all_dirs
  • 第一步获取所有子目录路径进入all_dirs文件
  • 第二步过滤掉有.git子目录和.git子目录的目录。 -x 选项是必需的,因为我们只需要消除完全匹配的行。

相比,这会更高效一些,因为它不会 运行 这么多子进程。但是,如果任何目录中有换行符,它会给出错误的输出。