特定のフォルダ内のすべてのgitリポジトリを(すばやく)見つける方法

特定のフォルダ内のすべてのgitリポジトリを(すばやく)見つける方法

素朴な方法ですが、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。これは、複数のディレクトリの内容を一覧表示するよりも効率が低くなります。

find1つの例外は、シェルの組み込み機能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' .

zshGNU 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最後に取り外してください。

サブフォルダは検索されません。

関連情報