Наивный подход есть find dir1 dir2 dir3 -type d -name .git | xargs -I {} dirname {}
, но он слишком медленный для меня, потому что у меня много глубоких структур папок внутри git-репозиториев (по крайней мере, я думаю, что это причина). Я читал о том, что могу использовать, prune
чтобы предотвратить поиск в каталогах, как только он что-то найдет, но есть две вещи. Я не уверен, как это работает (я имею в виду, я не понимаю, что prune
делает, хотя я прочитал man-страницу), и во-вторых, это не сработает в моем случае, потому что это помешает find
вернуться в .git
папку, но не во все другие папки.
Так что мне действительно нужно:
для всех подкаталогов проверьте, содержат ли они .git
папку, а затем остановите поиск в этой ветви файловой системы и сообщите результат. Было бы идеально, если бы это также исключало любые скрытые каталоги из поиска.
getpof .git
это то, что я использую. github.com/thrig/scripts/blob/master/filesys/getpof.cОтветы:
Хорошо, я все еще не совсем уверен, как это работает, но я проверил это, и это работает.
Я с нетерпением жду, чтобы сделать то же самое быстрее.
источник
-prune
так: вы начинаете с корня дерева, перемещаете его вниз, а когда применяется определенное условие, вы обрезаете целое поддерево (например, «обрезка»), поэтому вы больше не будете смотреть на другие узлы в этом поддереве. ,-type d
для которых условиеtest -e ...
истинно, и если оно истинно, мы выполняем действия,-print -prune
что означает печать и вырезание поддерева, верно?find . -type d -exec test -e '{}/.git' \; -print -prune | parallel cd "{}" \&\& git pull --rebase
GNUparallel
- очень удобная заменаxargs
Возможное решение
Для GNU
find
и других реализаций, которые поддерживают-execdir
:(см. комментарии)
Ранее обсужденные вещи
Решение, если обрезка ниже
.git
достаточноЕсли
-printf '%h'
поддерживается (как в случае с GNUfind
), нам не нужноdirname
:Как только он находит папку
.git
в текущем пути, он выводит ее, а затем перестает смотреть дальше вниз по поддереву.Решение, если все дерево папок должно быть удалено, как только
.git
найденИспользуя,
-quit
если вашfind
поддерживает это:(Согласно этому подробному сообщению Стефана Шазеласа
-quit
поддерживается в GNU и FreeBSD,find
а также в NetBSD-exit
.)Снова,
-printf '%h'
если поддерживается:Решение для обрезки на том же уровне, что и
.git
папкаСм. Часть «Возможное решение» для текущего решения этой конкретной проблемы.
(О, и очевидно, что решения, использующие,
xargs
предполагают, что в путях нет новых строк, в противном случае вам понадобится магия с нулевым байтом.)источник
dir1
содержит две директорииdirx
иdiry
каждая из них содержит.git
директорию, это только отчетыdirx/.git
dir1/.git
, что если оно существует, оно все еще спускаетсяdir1/dirx
, что, исходя из моего прочтения требования ОП, нежелательноВ идеале вы должны сканировать деревья каталогов для каталогов, которые содержат
.git
записи, и прекращать поиск дальше по ним (при условии, что у вас нет дополнительных репозиториев git внутри репозиториев git).Проблема состоит в том, что при стандартной
find
проверке такого типа (что каталог содержит.git
запись) требуется создание процесса, который выполняетtest
утилиту с использованием-exec
предиката, что будет менее эффективно, чем перечисление содержимого нескольких каталогов.Исключением может быть использование
find
встроеннойbosh
оболочки (POSIXified форка оболочки Bourne, разработанной @schily ), которая имеет-call
предикат для оценки кода в оболочке без необходимости создавать новый интерпретатор sh:Или используйте
perl
sFile::Find
:Дольше, но быстрее, чем
zsh
's'printf '%s\n' **/.git(:h)
(который опускается во все не скрытые каталоги) или GNUfind
,find . -name '.?*' -prune -o -type d -exec test -e '{}/.git' \; -prune -print
который запускает однуtest
команду в новом процессе для каждого не скрытого каталога.источник
.git
может быть файл - черезgit worktree
-d
с на-e
.Если вы используете locate, вы можете найти каталоги с:
Список результатов быстр, и дальнейшая обработка также проста.
источник
locate '*/.git'
должно быть достаточно.использование
time
это, чтобы увидеть разницу с и без-prune
.Это основано на решении в
man find
. Вы можете отредактироватьCVS
и,svn
если не требуется. Содержание man-страницы следуетУчитывая следующий каталог проектов и связанные с ними административные каталоги SCM, выполните эффективный поиск корней проектов:
В этом примере
-prune
предотвращается ненужный спуск в каталоги, которые уже были обнаружены (например, мы не ищемproject3/src
, потому что мы уже нашлиproject3/.svn
), но обеспечивает обнаружение дочерних каталогов (project2
иproject3
).источник