L'approche naïve est find dir1 dir2 dir3 -type d -name .git | xargs -I {} dirname {}
, mais c'est trop lent pour moi, car j'ai des structures de dossiers très profondes dans les dépôts git (du moins je pense que c'est la raison). J'ai lu à propos de cela que je peux utiliser prune
pour empêcher find de récurser dans les répertoires une fois qu'il a trouvé quelque chose, mais il y a deux choses. Je ne sais pas comment cela fonctionne (je veux dire que je ne comprends pas ce qui se prune
passe bien que j'aie lu la page de manuel) et la seconde, cela ne fonctionnerait pas dans mon cas, car cela empêcherait find
de rentrer dans le .git
dossier mais pas dans tous d'autres dossiers.
Donc ce dont j'ai réellement besoin c'est:
pour tous les sous-répertoires, vérifiez s'ils contiennent un .git
dossier et si c'est le cas, arrêtez de chercher dans cette branche de système de fichiers et rapportez le résultat. Ce serait parfait si cela excluait également les répertoires cachés de la recherche.
getpof .git
c'est ce que j'utilise. github.com/thrig/scripts/blob/master/filesys/getpof.cRéponses:
D'accord, je ne sais toujours pas totalement comment cela fonctionne, mais je l'ai testé et cela fonctionne.
J'ai hâte de faire la même chose plus rapidement.
la source
-prune
cette façon: vous commencez à la racine d'un arbre, vous le descendez et lorsqu'une certaine condition s'applique, vous coupez un sous-arbre entier (comme un véritable "élagage"), donc vous ne regarderez plus de nœuds dans ce sous-arbre .-type d
pour quelle conditiontest -e ...
est vraie et si elle est vraie, nous exécutons des actions-print -prune
qui signifient l'imprimer et couper le sous-arbre, non?find . -type d -exec test -e '{}/.git' \; -print -prune | parallel cd "{}" \&\& git pull --rebase
GNUparallel
est un remplacement très pratique pourxargs
Solution possible
Pour GNU
find
et autres implémentations qui prennent en charge-execdir
:(voir les commentaires)
Trucs discutés précédemment
Solution si l'élagage ci
.git
- dessous est suffisantSi
-printf '%h'
est pris en charge (comme dans le cas des GNUfind
), nous n'avons pas besoindirname
:Une fois qu'il rencontre un dossier
.git
dans le chemin actuel, il le sortira et cessera de regarder plus loin dans le sous-arbre.Solution si l'arborescence de dossiers entière doit être élaguée une fois a
.git
trouvéUtilisation
-quit
si votrefind
support:(Selon ce post détaillé de Stéphane Chazelas
-quit
est pris en charge dans GNU et FreeBSDfind
et dans NetBSD as-exit
.)Encore une fois avec
-printf '%h'
si pris en charge:Solution d'élagage au même niveau que l'emplacement du
.git
dossierVoir la partie «Solution possible» pour la solution actuelle de ce problème particulier.
(Oh et évidemment, les solutions utilisant
xargs
supposent qu'il n'y a pas de nouvelle ligne dans les chemins, sinon vous auriez besoin d'une magie à octets nuls.)la source
dir1
contient deux répertoiresdirx
etdiry
que chacun contient un.git
répertoire, cela ne signale quedirx/.git
dir1/.git
existe, elle descend toujoursdir1/dirx
, ce qui, sur la base de ma lecture de l'exigence d'OP, n'est pas souhaitéIdéalement, vous voudriez explorer les arborescences de répertoires pour les répertoires qui contiennent une
.git
entrée et arrêter de chercher plus loin dans ces répertoires (en supposant que vous n'avez plus de git repos dans git repos).Le problème est qu'avec le standard
find
, faire ce genre de vérification (qu'un répertoire contient une.git
entrée) implique de générer un processus qui exécute untest
utilitaire en utilisant le-exec
prédicat, ce qui sera moins efficace que de lister le contenu de quelques répertoires.Une exception serait si vous utilisez la fonction
find
intégrée dubosh
shell (un fork POSIXified du shell Bourne développé par @schily ) qui a un-call
prédicat pour évaluer le code dans le shell sans avoir à générer un nouvel interpréteur sh:Ou l' utilisation
perl
deFile::Find
:Plus, mais plus vite que
zsh
l «printf '%s\n' **/.git(:h)
(qui descend dans tous les répertoires non cachés), ou GNUfind
» sfind . -name '.?*' -prune -o -type d -exec test -e '{}/.git' \; -prune -print
qui exécute unetest
commande dans un nouveau processus pour chaque répertoire non caché.la source
.git
peut aussi être un fichier - viagit worktree
-d
s en-e
.Si vous utilisez Locate, vous pouvez trouver des répertoires avec:
La liste des résultats est rapide et le traitement ultérieur est également facile.
la source
locate '*/.git'
devrait suffire.Utilisation
time
cela, pour voir la différence avec et sans-prune
.Ceci est basé sur une solution dans le
man find
. Vous pouvez modifier leCVS
etsvn
si ce n'est pas nécessaire. le contenu de la page de manuel suitÉtant donné le répertoire de projets suivant et les répertoires administratifs SCM associés, effectuez une recherche efficace des racines des projets:
Dans cet exemple,
-prune
empêche la descente inutile dans des répertoires qui ont déjà été découverts (par exemple, nous ne recherchons pasproject3/src
, car nous avons déjà trouvéproject3/.svn
), mais garantit que les répertoires frères (project2
etproject3
) sont trouvés.la source