Adicionar recursivamente arquivos por padrão


172

Como adiciono recursivamente arquivos por um padrão (ou glob) localizado em diretórios diferentes?

Por exemplo, eu gostaria de adicionar A/B/C/foo.javae D/E/F/bar.java(e vários outros arquivos java) com um comando:

git add '*.java'

Infelizmente, isso não funciona como o esperado.


2
Funciona para mim (Mac OS X, Git 1.7.1+). Qual versão do SO e Git você está usando?
Chris Johnsen

3
Se você possui alguns .javaarquivos (já rastreados) em seu diretório atual, pode estar enfrentando uma manipulação complicada , er, de curinga entre o bash e o "auxiliar" da linha de comando do msys . Não tenho certeza sobre uma solução. Você pode tentar várias camadas de aspas: git add '"*.java"'(as aspas simples são usadas pelo bash para impedir a expansão da glob, as aspas duplas são tomadas pela camada msys para impedir a expansão da glob).
Chris Johnsen

1
Obrigado pela observação. Infelizmente, isso também não funciona. Eles dizem que o foi corrigido, mas eu já tenho a versão mais recente.
Michel Krämer


1
git add *.javafunciona para mim (em powershell com o cliente GitHub)
ThaDafinser

Respostas:


89

A resposta de Sergio Acosta é provavelmente a sua melhor aposta, se alguns dos arquivos a serem adicionados ainda não estiverem rastreados. Se você deseja limitar-se aos arquivos que o git já conhece, você pode combinar git-ls-filescom um filtro:

git ls-files [path] | grep '\.java$' | xargs git add

O Git não fornece mecanismos sofisticados para fazer isso sozinho, pois é basicamente um problema de shell: como você obtém uma lista de arquivos para fornecer como argumentos para um determinado comando.


8
Obrigado! Eu melhorei um pouco o seu comando e agora está fazendo o que estava procurando:git ls-files -co --exclude-standard | grep '\.java$' | xargs git add
Michel Krämer

169

Você pode usar git add [path]/\*.javapara adicionar arquivos java de subdiretórios,
por exemplo , git add ./\*.javapara o diretório atual.

Da git adddocumentação :

Adiciona conteúdo de todos os *.txtarquivos no Documentationdiretório e seus subdiretórios:

$ git add Documentation/\*.txt

Observe que o asterisco *é citado no shell neste exemplo; isso permite que o comando inclua os arquivos dos subdiretórios do Documentation/diretório


2
@ MichelKrämer provavelmente não era, mas é agora.
Alberto

7
Esta é a melhor solução, funciona no Windows também.
TheTFo

1
msgstr "asterisco * é citado do shell". Eu acho que você quer dizer "escapou". Em qualquer caso, a barra invertida impede que o shell a expanda.
gwideman

1
@gwideman Acho que você está certo, mas não sou eu. É citação dos documentos git-scm.com/docs/git-add#_examples
Sergey Glotov

62

Com zshvocê pode executar:

git add "**/*.java"

e todos os seus *.javaarquivos serão adicionados recursivamente.


Obrigado por isso, mas estou trabalhando com o msysgit no Windows e ele tem apenas um bash.
Michel Krämer

1
Bem, vejo que existe um zshshell para o Windows ... você fará um favor a si mesmo em usá-lo em vez de bash, imho.
Olivier Verdier

1
A porta do zsh para Windows é baseada em uma versão muito antiga e trava o tempo todo (por exemplo, quando eu entro ls).
Michel Krämer

Uau, perfeito. Eu não sabia sobre esse recurso!
Tomáš Votruba

1
Isso não tem nada a ver com zsh. Eu acho que essa resposta perde o ponto que você deseja percorrer o caminho com curingas intactos para git e deixar o git processá-lo. Portanto, você deseja impedir que o shell que você está usando expanda os caracteres curinga. Para fazer isso, é necessário citá-lo de alguma maneira apropriada para o shell que você está usando. Veja outras respostas para obter detalhes.
gwideman

55

Um tópico pouco interessante (não especificamente relacionado ao git), mas se você estiver no linux / unix, uma solução alternativa pode ser:

find . -name '*.java' | xargs git add

E se você espera caminhos com espaços:

find . -name '*.java' -print0 | xargs -0 git add

Mas eu sei que não é exatamente o que você pediu.


6
Problema menor com essa abordagem - se você "encontrar" um arquivo correspondente ao seu .gitignore, o git reclamará que você está tentando adicionar um arquivo que você pediu para ignorar.
yoyo

2
@yoyo - Acabei de adicionar -f na extremidade, e que fixa que
Maslow

5
@ Maslow, que adicionará à força o arquivo, mesmo que ele devesse ser ignorado (com base em .gitignore). Eu prefiro para obter a queixa e não adicionar o arquivo (que é o comportamento padrão.)
yoyo

Como isso é melhor do que deixar o git executar a expansão de curinga?
gwideman

12

A resposta de Sergey (não me credite) está funcionando:

You can use git add [path]/\*.java

com um git recente:

$git version
git version 1.7.3.4

Arquivos para o teste:

$find -name .git -prune -o -type f -print | sort
./dirA/dirA-1/dirA-1-1/file1.txt
./dirA/dirA-1/dirA-1-2/file2.html
./dirA/dirA-1/dirA-1-2/file3.txt
./dirA/dirA-1/file4.txt
./dirB/dirB-1/dirB-1-1/file5.html
./dirB/dirB-1/dirB-1-1/file6.txt
./file7.txt

Status do Git:

$git status -s
?? dirA/
?? dirB/
?? file7.txt

Adicionando * .txt:

$git add \*.txt

Status atualizado:

$git status -s
A  dirA/dirA-1/dirA-1-1/file1.txt
A  dirA/dirA-1/dirA-1-2/file3.txt
A  dirA/dirA-1/file4.txt
A  dirB/dirB-1/dirB-1-1/file6.txt
A  file7.txt
?? dirA/dirA-1/dirA-1-2/file2.html
?? dirB/dirB-1/dirB-1-1/file5.html

8

Se você já está acompanhando seus arquivos e fez alterações neles, e agora deseja adicioná-los seletivamente com base em um padrão, pode usar o --modifiedsinalizador

git ls-files --modified | grep '<pattern>' | xargs git add

Por exemplo, se você deseja adicionar apenas as alterações de CSS a esse commit, você pode fazer

git ls-files --modified | grep '\.css$' | xargs git add

Veja man git-ls-filespara mais sinalizadores


5

Apenas use git add *\*.java. Isso adicionará todos os arquivos .java no diretório raiz e todos os subdiretórios.


Ótima resposta. Git add * / pom.xml para adicionar todos os nomes de arquivos pom.xml.
Philip Rego

4

Adicionando uma solução de linha de comando do Windows que ainda não foi mencionada:

for /f "delims=" %G in ('dir /b/s *.java') do @git add %G

3

Eu queria adicionar apenas arquivos que tivessem uma determinada string com base em git status:

git status | grep string | xargs git add

e, em seguida, conseguiu git commit -m 'commit msgconfirmar todos os arquivos alterados com "string" no título do arquivo


2

Como mencionado em " git: como adiciono recursivamente todos os arquivos em uma subárvore de diretório que correspondem a um padrão glob? ", Se você escapar ou citar corretamente o pathspec globbing (como'*.java' ), sim, git add'*.java'

O Git 2.13 (Q2 2017) melhora isso para adicionar interativo:

Veja commit 7288e12 (14 de março de 2017) por Jeff King ( peff) .
(Mesclado por Junio ​​C Hamano - gitster- na confirmação 153e0d7 , 17 de março de 2017)

add --interactive: não expanda pathspecs com ls-files

Quando queremos obter a lista de arquivos modificados, primeiro expandimos os códigos de caminho fornecidos pelo usuário com " ls-files" e, em seguida, alimentamos a lista resultante de caminhos como argumentos para " diff-index" e " diff-files".
Se o seu pathspec se expandir para um grande número de caminhos, você poderá encontrar um dos dois problemas:

  1. O sistema operacional pode reclamar do tamanho da lista de argumentos e se recusar a executar. Por exemplo:

    $ (ulimit -s 128 && git add -p drivers)
    Can't exec "git": Argument list too long at .../git-add--interactive line 177.
    Died at .../git-add--interactive line 177.
    

Está no linux.gitrepositório, que possui cerca de 20K arquivos no diretório "drivers" (nenhum deles modificado neste caso). O ulimit -struque " " é necessário para mostrar o problema no Linux, mesmo para um conjunto tão grande de caminhos.
Outros sistemas operacionais têm limites muito menores (por exemplo, um caso do mundo real foi visto com apenas 5K arquivos no OS X).

  1. Mesmo quando funciona, é muito lento. O código do pathspec não é otimizado para um grande número de caminhos. Aqui está o mesmo caso sem o ulimit:

    $ time git add -p drivers
      No changes.
    
    real  0m16.559s
    user    0m53.140s
    sys 0m0.220s
    

Nós podemos melhorar isso pulando " ls-files" completamente, e apenas alimentando o pathspecs original aos comandos diff.

Historicamente, a linguagem pathspec suportada por " diff-index" era mais fraca, mas esse não é mais o caso.


1

colocar linha em ~ / .gitconfig

[alias] addt = !sh -c 'git ls-files | grep \"\\.$1*\" | xargs git add' -

Se você deseja adicionar todos os arquivos java modificados, basta: git addt java

Da mesma forma, se você deseja adicionar todos os arquivos python modificados, basta: git addt py

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.