2017-07-30 134 views
2

如何使用find来获取所有没有.git文件夹的文件夹?使用find来获取所有没有.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 
$ 
+0

我认为没有办法做到“纯粹”,但下面的答案是确切的。 – linuxfan

+0

另外 - 请注意换行符分隔的文件列表不一定是安全的:如果有人运行'mkdir -p ./$'\ n'/ etc/passwd',这取决于您的'find'的确切版本和它的'-print'的实现,你可以在你的输出列表中获得'/ etc/passwd'。这种不明确性是'find -print0'的很大动机,尽管符合POSIX的'find -exec'也可以用来从'find'中获得确切的名字(字面换行符,控制序列和全部)。 –

回答

3

效率低下(运行一堆子过程),但下面将做的工作与GNU或BSD现代find

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

如果你不能保证具有与POSIX标准不能保证任何功能的find,那么你可能需要采取更效率的损失(以使{}自己的道理,而不是一个字符串,由具有壳运行测试):

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

这是通过使用-exec作谓语,runni find不支持内置的测试。

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

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

Charles' answer相比,这样会更有效率,因为它不会运行如此多的子过程。但是,如果任何目录中有换行符,则会输出错误信息。

+1

它是否更高效取决于你的树与'.git'兄弟姐妹的深度(以及没有它们的目录有多少);缺乏'-prune'意味着你正在告诉'找到'来缓解他们。 –

相关问题