パターンでファイルを再帰的に追加する


172

異なるディレクトリにあるパターン(またはグロブ)でファイルを再帰的に追加するにはどうすればよいですか?

たとえば、1つのコマンドでA/B/C/foo.javaおよびD/E/F/bar.java(およびその他のいくつかのJavaファイル)を追加したいとします。

git add '*.java'

残念ながら、それは期待どおりに機能しません。


2
それは私のために動作します(Mac OS X、Git 1.7.1以降)。使用しているOSとGitのバージョンは何ですか?
Chris Johnsen、

3
.java現在のディレクトリにいくつかの(すでに追跡されている)ファイルがある場合は、bashとmsysコマンドラインの「ヘルパー」の複雑なワイルドカード処理が実行されている可能性があります。解決策はわかりません。引用符の複数のレイヤーを試すこともできますgit add '"*.java"'(一重引用符はグロブの展開を防ぐためにbashによって取られ、二重引用符はグロブの展開を防ぐためにmsysレイヤーによって取られます)。
Chris Johnsen、

1
メモありがとうございます。残念ながら、それもうまくいきません。彼らは修正されたと言いますが、私はすでに最新バージョンを持っています。
ミシェルクレーマー


1
git add *.java私のために動作します(GitHubクライアントを備えたPowerShellで)
ThaDafinser

回答:


88

追加するファイルの一部がまだ追跡されていない場合は、セルジオアコスタの答えがおそらく最善の策です。gitがすでに知っているファイルに制限したい場合git-ls-filesは、フィルターと組み合わせることができます:

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

これは基本的にシェルの問題であるため、Gitはこれ自体を行うための特別なメカニズムを提供していません。特定のコマンドの引数として提供するファイルのリストをどのように取得するのですか。


8
ありがとう!私はあなたのコマンドを少し改善しました、そして今それは私が探していたものを実行しています:git ls-files -co --exclude-standard | grep '\.java$' | xargs git add
ミシェル・クレーマー

169

あなたは使用することができgit add [path]/\*.java、サブディレクトリからjavaファイルを追加する
などgit add ./\*.java、現在のディレクトリのために。

git addドキュメントから:

ディレクトリとそのサブディレクトリの*.txt下にあるすべてのファイルからコンテンツを追加しますDocumentation

$ git add Documentation/\*.txt

*この例では、アスタリスクはシェルから引用されていることに注意してください。これにより、コマンドはディレクトリのサブディレクトリからのファイルを含めることができますDocumentation/


2
@MichelKrämerはおそらくそうではありませんでしたが、今はそうです。
アルベルト

7
これは最良の解決策であり、Windowsでも機能します。
TheTFo 2014年

1
「アスタリスク*はシェルから引用されます」。「逃げた」という意味だと思います。いずれにしても、バックスラッシュはシェルがそれを拡張するのを防ぎます。
gwideman 2018年

1
@gwideman私はあなたが正しいと思うが、それは私ではない。docs git-scm.com/docs/git-add#_examples
セルゲイ

62

zshあなたが実行することができます:

git add "**/*.java"

すべての*.javaファイルが再帰的に追加されます。


そのおかげで、私はWindowsでmsysgitを使用していて、bashしかありません。
ミシェルクレーマー

1
まあ、私はzshウィンドウ用のシェルがあることを知っています...あなたは自分でbashの代わりにそれを使用することを好みます、imho。
Olivier Verdier

1
zshのWindowsへの移植は非常に古いバージョンに基づいており、常にクラッシュします(たとえば、と入力するとls)。
ミシェルクレーマー

うわー、完璧。その機能について知りませんでした!
トマーシュVotruba

1
これはzshとは関係ありません。この回答は、ワイルドカードをそのままにしてパスをgitに渡し、gitに処理させたいという点を逃していると思います。したがって、使用しているシェルがワイルドカードを展開しないようにする必要があります。これを行うには、使用しているシェルに適した方法で引用する必要があります。詳細については、他の回答を参照してください。
gwideman 2018年

55

少しずれたトピック(特にgit関連ではありません)ですが、linux / unixを使用している場合の回避策は次のとおりです。

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

スペースを含むパスが必要な場合:

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

しかし、私はそれが正確にあなたが尋ねたものではないことを知っています。


6
このアプローチの軽微な問題-.gitignoreと一致するファイルを「見つけた」場合、gitは無視するように指示したファイルを追加しようとしていると文句を言います。
ヨーヨー

2
@yoyo-私は最後に-fを追加しました、そしてそれはそれを修正しました
Maslow

5
@Maslow、それは(.gitignoreに基づいて)無視されることになっていたファイルを強制的に追加します。ファイルを追加するのではなく、苦情を受け取りたい(デフォルトの動作です)
yoyo

これはgitにワイルドカード拡張を実行させるよりもどのように優れていますか?
gwideman 2018年

12

セルゲイの答え(私を信用しないでください)は機能しています:

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

最近のgitで:

$git version
git version 1.7.3.4

テスト用のファイル:

$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

Gitステータス:

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

* .txtの追加:

$git add \*.txt

更新されたステータス:

$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

すでにファイルを追跡していて、それらに変更を加えた後、パターンに基づいてそれらを選択的に追加したい場合は、--modifiedフラグを使用できます

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

たとえば、CSSの変更のみをこのコミットに追加したい場合は、

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

man git-ls-filesその他のフラグについては、


5

だけを使用してくださいgit add *\*.java。これにより、すべての.javaファイルがルートディレクトリとすべてのサブディレクトリに追加されます。


すばらしい答えです。私はgit add * / pom.xmlを実行して、すべてのファイルpom.xmlを追加しました。
Philip Rego

4

まだ言及されていないWindowsコマンドラインソリューションの追加:

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

3

私はに基づいて特定の文字列を持つファイルのみを追加したかったgit status

git status | grep string | xargs git add

そしてgit commit -m 'commit msg、ファイルのタイトルに「文字列」を含むすべての変更されたファイルをコミットすることができました


2

git:グロブパターンに一致するディレクトリサブツリー内のすべてのファイルを再帰的に追加するにはどうすればよいですか?」で説明したように'*.java'、パススペックグロビング(のように)を適切にエスケープまたは引用すると、はい、git add'*.java'

Git 2.13(2017年第2四半期)では、インタラクティブな追加の機能が改善されています。

Jeff King(によるコミット7288e12(2017年3月14日)を参照してください。(合併によりJunio C浜野- -153e0d7コミットし、2017年3月17日)をpeff
gitster

add --interactive:パス指定を展開しない ls-files

変更されたファイルのリストを取得する場合、最初にユーザー提供のパス仕様を「ls-files」で展開し、次に、結果のパスのリストを引数として「diff-index」と「diff-files」にフィードします。
pathspecが多数のパスに展開される場合、次の2つの問題のいずれかが発生する可能性があります。

  1. OSは引数リストのサイズについて文句を言い、実行を拒否するかもしれません。例えば:

    $ (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.
    

これlinux.gitは、「drivers」ディレクトリに約20Kのファイルがあるリポジトリにあります(この場合、ファイルは変更されていません)。このulimit -sような巨大なパスのセットであっても、Linuxで問題を示すには「」のトリックが必要です。
他のオペレーティングシステムでは、制限がはるかに小さくなっています(たとえば、OS Xでは5Kファイルのみで実際のケースが見られました)。

  1. それが機能するときでさえ、それは本当に遅いです。pathspecコードは、膨大な数のパスに対して最適化されていません。以下は、ulimitを使用しない同じケースです。

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

ls-files」を完全にスキップして、元のパス仕様をdiffコマンドに渡すだけで、これを改善できます。

歴史的に、「diff-index」でサポートされているパススペック言語はより弱いものでしたが、もはやそうではありません。


1

〜/ .gitconfigに行を追加します

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

変更したすべてのJavaファイルを追加する場合は、次のようにします。 git addt java

同様に、変更したすべてのpythonファイルを追加する場合は、次のようにします。 git addt py

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.