Recursively add files by pattern

GitGlobFilepattern

Git Problem Overview


How do I recursively add files by a pattern (or glob) located in different directories?

For example, I'd like to add A/B/C/foo.java and D/E/F/bar.java (and several other java files) with one command:

git add '*.java'

Unfortunately, that doesn't work as expected.

Git Solutions


Solution 1 - Git

You can use git add [path]/\*.java to add java files from subdirectories,
e.g. git add ./\*.java for current directory.

From git add documentation:

> Adds content from all *.txt files under Documentation directory and its subdirectories: > $ git add Documentation/*.txt > > Note that the asterisk * is quoted from the shell in this example; this lets the command include the files from subdirectories of Documentation/ directory.

Solution 2 - Git

Sergio Acosta's answer is probably your best bet if some of the files to be added may not already be tracked. If you want to limit yourself to files git already knows about, you could combine git-ls-files with a filter:

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

Git doesn't provide any fancy mechanisms for doing this itself, as it's basically a shell problem: how do you get a list of files to provide as arguments to a given command.

Solution 3 - Git

With zsh you can run:

git add "**/*.java"

and all your *.java files will be added recursively.

Solution 4 - Git

A bit off topic (not specifically git related) but if you're on linux/unix a workaround could be:

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

And if you expect paths with spaces:

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

But I know that is not exactly what you asked.

Solution 5 - Git

Sergey's answer (don't credit me) is working:

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

with a recent git:

$git version
git version 1.7.3.4

Files for the test:

$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 status:

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

Adding *.txt:

$git add \*.txt

Updated status:

$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

Solution 6 - Git

If you are already tracking your files and have made changes to them and now you want to add them selectively based on a pattern, you can use the --modified flag

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

For example, if you only want to add the CSS changes to this commit, you can do

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

See man git-ls-files for more flags

Solution 7 - Git

Just use git add *\*.java. This will add all .java files in root directory and all subdirectories.

Solution 8 - Git

As it's not mentioned here, consider also the "magic signature" :/ to recursively add anything matching below the project root:

git add :/*.{java,pom}

Tx to: https://stackoverflow.com/a/64210713/2586761

Solution 9 - Git

Adding a Windows command line solution that was not yet mentioned:

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

Solution 10 - Git

I wanted to only add files that had a certain string based on git status:

and then was able to git commit -m 'commit msg to commit all changed files with "string" in the title of the file

Solution 11 - Git

As mentioned in "git: How do I recursively add all files in a directory subtree that match a glob pattern?", if you properly escape or quote your pathspec globbing (like '*.java'), then yes, git add '*.java'

Git 2.13 (Q2 2017) improves that for interactive add:

See commit 7288e12 (14 Mar 2017) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 153e0d7, 17 Mar 2017)

> ## add --interactive: do not expand pathspecs with ls-files

> When we want to get the list of modified files, we first expand any user-provided pathspecs with "ls-files", and then feed the resulting list of paths as arguments to "diff-index" and "diff-files".
If your pathspec expands into a large number of paths, you may run into one of two problems:

> 1. The OS may complain about the size of the argument list, and refuse to run. For example:

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

> That's on the linux.git repository, which has about 20K files in the "drivers" directory (none of them modified in this case). The "ulimit -s" trick is necessary to show the problem on Linux even for such a gigantic set of paths.
Other operating systems have much smaller limits (e.g., a real-world case was seen with only 5K files on OS X).

> 2. Even when it does work, it's really slow. The pathspec code is not optimized for huge numbers of paths. Here's the same case without the ulimit:

> $ time git add -p drivers No changes.

> real 0m16.559s user 0m53.140s sys 0m0.220s

> We can improve this by skipping "ls-files" completely, and just feeding the original pathspecs to the diff commands.

Historically the pathspec language supported by "diff-index" was weaker, but that is no longer the case.

Solution 12 - Git

put line in ~/.gitconfig

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

If you want to add all modified java file can just do: git addt java

Samely, if you want to add all modified python file can just do: git addt py

Solution 13 - Git

A variation that I used in a GNUmakefile

.PHONY: docs
docs:
	@echo docs
	bash -c "if pgrep MacDown; then pkill MacDown; fi"
	bash -c 'cat $(PWD)/HEADER.md                >  $(PWD)/README.md'
	bash -c 'cat $(PWD)/COMMANDS.md              >> $(PWD)/README.md'
	bash -c 'cat $(PWD)/FOOTER.md                >> $(PWD)/README.md'
	bash -c 'pandoc -s README.md -o index.html'
	bash -c "if hash open 2>/dev/null; then open README.md; fi || echo failed to open README.md"
	#git add --ignore-errors *.md
	git ls-files -co --exclude-standard | grep '\.md/$\' | xargs git 



Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichel Kr&#228;merView Question on Stackoverflow
Solution 1 - GitSergey GlotovView Answer on Stackoverflow
Solution 2 - GitCascabelView Answer on Stackoverflow
Solution 3 - GitOlivier VerdierView Answer on Stackoverflow
Solution 4 - GitSergio AcostaView Answer on Stackoverflow
Solution 5 - GitAlbertoView Answer on Stackoverflow
Solution 6 - GitRamView Answer on Stackoverflow
Solution 7 - GitJan LovstrandView Answer on Stackoverflow
Solution 8 - GitptimView Answer on Stackoverflow
Solution 9 - GitselalererView Answer on Stackoverflow
Solution 10 - GitbdaninView Answer on Stackoverflow
Solution 11 - GitVonCView Answer on Stackoverflow
Solution 12 - GitHong EmrysView Answer on Stackoverflow
Solution 13 - GitRandyMcMillanView Answer on Stackoverflow