递归地按模式添加文件

我如何递归地通过位于不同目录的模式(或glob)添加文件?

例如,我想用一个命令添加A/B/C/foo.javaD/E/F/bar.java(以及其他几个java文件):

git add '*.java'

不幸的是,这并没有像预期的那样起作用。

95650 次浏览

有点偏离主题(不是特别与git相关),但如果你在linux/unix上,一个变通方法可以是:

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

如果你期望路径有空格

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

但我知道这不是你想要的。

使用zsh你可以运行:

git add "**/*.java"

并且你所有的*.java文件将被递归添加。

塞尔吉奥·阿科斯塔的回答可能是你最好的选择,如果一些要添加的文件可能还没有被跟踪。如果你想把自己限制在git已经知道的文件中,你可以把git-ls-files和一个过滤器结合起来:

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

Git本身并没有提供任何花哨的机制来实现这一点,因为它基本上是一个shell问题:如何获得作为给定命令的参数提供的文件列表。

你可以使用git add [path]/\*.java
子目录中添加java文件 例如:git add ./\*.java表示当前目录

git add文档:

添加来自Documentation目录及其子目录下所有*.txt文件的内容:

$ git add Documentation/\*.txt

注意,星号*引用自本例中的shell;这让该命令包括Documentation/目录子目录中的文件。

谢尔盖的回答(不要相信我)正在工作:

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

如果你已经在跟踪你的文件,并对它们进行了更改,现在你想根据模式有选择地添加它们,你可以使用--modified标志

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

例如,如果您只想将CSS更改添加到此提交,您可以这样做

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

更多标志请参见man git-ls-files

正如“git:如何递归地添加目录子树中匹配glob模式的所有文件?”中提到的,如果你正确转义或引用你的路径spec通配符(如'*.java'),那么是的,git添加'*.java'

Git 2.13(2017年第二季度)改进了交互式添加:

参见提交7288年e12汽油 (14 Mar 2017) by 杰夫·金(peff) (由Junio C Hamano—gitster提交153年e0d7中合并,17 Mar 2017)

add --interactive:不使用ls-files扩展路径规格

当我们想要获得修改文件的列表时,我们首先用"ls-files"展开任何用户提供的路径规格,然后将得到的路径列表作为参数提供给"diff-index"和"diff-files" 如果您的路径规格扩展为大量的路径,您可能会遇到以下两个问题之一:

  1. 操作系统可能会抱怨参数的大小 列出,并拒绝参选。例如:< / p >

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

  1. 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.

我只想添加基于git status的特定字符串的文件:

git status | grep string | xargs git add < /代码> < / p >

然后能够git commit -m 'commit msg提交所有更改的文件,在文件标题中使用“string”

只需使用git add *\*.java即可。这将添加根目录和所有子目录下的所有。java文件。

添加一个之前没有提到的Windows命令行解决方案:

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

把行放在~/.gitconfig中

< p > <代码>(别名) Addt = !sh -c 'git ls-files | grep \"\\。$1*\" | xargs git add' -

如果你想添加所有修改过的java文件,只需做: git addt java < / p > 同样,如果你想添加所有修改过的python文件,可以这样做: git addt py < / p >

由于这里没有提到,也可以考虑“神奇的签名":/来递归地添加任何匹配的项目根以下:

git add :/*.{java,pom}

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

我在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