2

How to use find to get all folders that have not a .git folder?

On this structure::

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

This::

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

get all folders except .git

I would like to get this::

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

2 回答 2

3

它效率低下(运行一堆子进程),但以下将使用 GNU 或现代 BSD 完成工作find

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

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

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

这通过-exec用作谓词运行find不支持内置的测试来工作。

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

于 2017-07-30T17:00:22.480 回答
1

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

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选项是必要的,因为我们只需要消除完全匹配的行。

与查尔斯的答案相比,这将更有效率,因为它不会运行这么多的子进程。但是,如果任何目录中包含换行符,则会给出错误的输出。

于 2017-07-31T05:06:54.850 回答