2017-07-30 133 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'意味着你正在告訴'找到'來緩解他們。 –

相關問題