素朴な方法ですが、find dir1 dir2 dir3 -type d -name .git | xargs -I {} dirname {}
gitリポジトリには深いフォルダ構造が多いので、私にとっては遅すぎます(少なくともそれが理由だと思います)。prune
何かを見つけた後、findがディレクトリに繰り返されるのを防ぐために使用できるものについて読んでいましたが、2つあります。これがどのように機能するのかよくわかりません(prune
マンページを読んでいますが、それが何であるかわかりません)。 2番目はファイルフォルダfind
への再帰をブロックするため、私の場合は機能しません。.git
ただし、すべてのフォルダ内の他のフォルダに繰り返されるわけではありません。
だから私に本当に必要なのは:
すべてのサブディレクトリのフォルダが含まれていることを確認し.git
、その場合はこのファイルシステムブランチで検索を停止し、結果を報告します。検索から隠されたディレクトリも除外すれば完璧です。
答え1
まあ、まだそれがどのように機能するのか完全にはわかりませんが、テストしてみました。
.
├── a
│ ├── .git
│ └── a
│ └── .git
└── b
└── .git
6 directories, 0 files
% find . -type d -exec test -e '{}/.git' ';' -print -prune
./a
./b
私はこの仕事をより速くすることを楽しみにしている。
答え2
理想的には、ディレクトリツリーをクロールしてエントリを含むディレクトリを見つけ、そのディレクトリの追加の検索を停止することをお勧め.git
します(gitリポジトリにもはやgitリポジトリがないと仮定します)。
問題は、標準を使用してfind
このチェック(ディレクトリにエントリが含まれているかどうか.git
)を実行すると、test
述語実行ユーティリティを使用してプロセスを作成することが含まれることです-exec
。これは、複数のディレクトリの内容を一覧表示するよりも効率が低くなります。
find
1つの例外は、シェルの組み込み機能bosh
(Bourneシェルで開発されたPOSIXifiedフォーク)を使用する場合です。@ヒリー)ここには、-call
新しいshインタプリタを生成せずにシェルでコードを評価する述語があります。
#! /path/to/bosh -
find . -name '.?*' -prune -o \
-type d -call '[ -e "$1/.git" ]' {} \; -prune -print
またはperl
以下を使用してくださいFile::Find
。
perl -MFile::Find -le '
sub wanted {
if (/^\../) {$File::Find::prune = 1; return}
if (-d && -e "$_/.git") {
print $File::Find::name; $File::Find::prune = 1
}
}; find \&wanted, @ARGV' .
zsh
GNU printf '%s\n' **/.git(:h)
(非表示のすべてのディレクトリに含まれている)またはGNU find
(非表示の各ディレクトリに対して新しいプロセスでコマンドを実行find . -name '.?*' -prune -o -type d -exec test -e '{}/.git' \; -prune -print
)よりも長いですが、高速です。test
2022年編集。最新バージョンのbusyboxには、プロセスをフォークして内部的に再実行せずにそのアプレットをfind
実行する機能があるため、まだboshまたはperlメソッドほど高速ではありません。[
test
busybox find . -type d -exec [ -e '{}/.git' ] ';' -prune -print
私のテストでは、GNUに対応するよりもはるかに高速ですfind
(git / cvs / svnリポジトリが混在しており、合計100,000を超えるディレクトリを含むローカルサンプルでは、boshの場合は0.25秒、Perlの場合は0.3秒、busyboxの場合0.7秒を得ました)。 )find
、GNUの場合は36秒find
、GNUの場合は2秒(gitリポジトリのサブディレクトリでもファイルを見つけるfind . -name .git -printf '%h\n'
ため、異なる結果が得られます)。.git
答え3
検索を使用すると、次の内容を含むディレクトリを見つけることができます。
locate .git | grep "/.git$"
結果のリストは高速で、追加の処理も簡単です。
答え4
ls -d */.git
使用後は.git
最後に取り外してください。
サブフォルダは検索されません。