Pętla w podkatalogach i uruchamianie poleceń w każdym z nich

47

Mam zestaw repozytoriów posortowanych w katalogach na podstawie ich VCS (Git, Mercurial, SVN). Dzięki Subversion mogłem uruchomić svn update *w katalogu nadrzędnym, który przechodziłby przez każdy katalog i aktualizował każde repozytorium zgodnie z oczekiwaniami. Tak nie jest w przypadku Git lub Mercurial.

Chciałbym wymyślić skrypt bash, który mogę uruchomić, aby dokładnie to zrobić, przeglądać katalogi i jedno git pulllub drugie hg pull. Po prostu nie mam dużego doświadczenia w tworzeniu skryptów bash.

Bryan Veloso
źródło
Można wyjaśnić, czy chcesz, aby polecenia były wykonywane rekurencyjnie (we wszystkich podfolderach), gdzie odpowiedź mj41 jest jedyną, której próbowałem (stąd i na innych stronach SO), która to robi.
r_alex_hall
* robi to z poprawką, o której wspominam w komentarzu na ten temat.
r_alex_hall

Odpowiedzi:

81
for dir in ~/projects/git/*; do (cd "$dir" && git pull); done
jtimberman
źródło
2
Dzięki ... ale muszę też wychwytywać błędy. Jak mogę to zrobić? Nigdy wcześniej nie programowałem w powłoce.
shashwat
23

Jeśli potrzebujesz rekurencji:

find . -type d -name .git -exec sh -c "cd \"{}\"/../ && pwd && git pull" \;

Spowoduje to zejście do wszystkich katalogów pod bieżącym i wykonanie ściągnięcia git na te podkatalogi, które mają katalog .git (możesz go ograniczyć -maxdepth).

Dennis Williamson
źródło
@thprivileges: clever!
Dennis Williamson
9
-execdirjest tu znacznie lepiej:find . -type d -name .git -execdir sh -c "pwd && git pull" \;
Daniel Kullmann
To jest lepsza odpowiedź w mojej subiektywnej opinii ... Od razu
zadziałało
W przeciwieństwie do pytania, które mnie tu połączyło, to polecenie faktycznie działało. Dziękuję Ci.
user1445967
7

Jeśli masz GNU Parallel http: // www.gnu.org/software/parallel/, możesz to zrobić:

cd ~/projects/git/; ls | parallel 'cd {} && git pull'

Będzie to działało równolegle, więc jeśli niektóre połączenia sieciowe serwerów git są wolne, może to przyspieszyć.

Obejrzyj wideo wprowadzające do GNU Parallel, aby dowiedzieć się więcej: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
źródło
Być może ls */upewnij się, że dajesz spójny wkład cd.
Joe Corneli,
4

To powinno działać

find . -maxdepth 1 -type d -name '.git' -exec sh -c 'cd "{}" && pwd && git pull' \;
mj41
źródło
usuwając -maxdepth 1flagę, jest to jedyne polecenie, które znalazłem podczas wielu wyszukiwań i prób, które wykonuje polecenie rekurencyjnie (we wszystkich podkatalogach, nie tylko w katalogach o jeden poziom niżej).
r_alex_hall
0

Aby to zrobić rekurencyjnie bez użycia, findaleforloop

for dir in ~/projects/git/*/*/; do (cd "$dir" && git pull); done
loretoparisi
źródło