开发者

How to grep files in git repo?

I love git grep to search in all files checked in to a repo. It's great. But is it possible to use it (or some other git command) to just use to find files (independent of content)?

At the moment I do t开发者_如何学编程his:

$ find . | grep middleware

which works but it's not using the git index which means it's going through every found file and it reports on files that are matching the .gitignore.

Any ideas for clever tricks?


Maybe you want git ls-files which lists the files in the index? (and automatically adjusts for your current directory inside the git work directory)


I think git ls-files will do the trick for you.

So:

 git ls-files "*middleware*"


You might consider a non-git solution in this case.

find itself has the ability to do what you want in a more efficient manner than piping its results into grep:

find . -name 'middleware*'

You will need to quote the pattern so that the * isn't expanded by the shell before being passed to find.

There is a powerful program called ack that is, well, better than grep, and one of my favorite uses for ack is exactly what you've mentioned -- finding files that match a pattern within a tree. ack uses perl regexps, not shell fileglobs, though.

ack -g middleware

If you want to search within those files, ack lets you do that more easily than writing a shell loop over the results of find that greps within each file. Compare the two and see which one you prefer:

for f in $(find . -name 'middleware*')
do
    grep 'pattern in file' $f
done

versus

ack -G 'middleware' 'pattern in file'

I highly recommend ack as something to add to your toolkit.


Pure git solution

git grep has built-in support to limit the grep to a glob of files. The other answers all use external tools to do the actual grepping, which misses the point.

Example from the git grep man page.

git grep 'time_t' -- '*.[ch]'

Looks for time_t in all tracked .c and .h files in the working directory and its subdirectories.

From the option descriptions.

-- Signals the end of options; the rest of the parameters are limiters.

<pathspec>…​ If given, limit the search to paths matching at least one pattern. Both leading paths match and glob(7) patterns are supported.

So to translate your example (which did not include something to limit the search however so I added it here):

$ find . -name '*.txt' | grep middleware

You would do:

$ git grep middleware -- '*.txt'


git now has matured search functionality (as the previous poster mentioned). You can search file names, extensions, by programming language.. You can search inside at file contents... etc.

You search when you log into GitHub, at the search field in the upper - left of the screen.

See this for details: https://help.github.com/en/articles/searching-code


I have the same problem regularily, and I just went and hacked git find – if you don’t use the Debian package you can just copy the git-find script to /usr/lib/git-core/ (or comparable) and enjoy it.

It can be used in several modes, the easiest of which is indeed:

git find \*middleware\*        # or
git find '*middleware*'        # which is short for
git find -name '*middleware*'

Combining is also possible (and almost as flexible as regular find, you just have to write the -a explicitly):

git find \( -name \*.java -o -name \*.js \) -a ! -ipath \*/test/\*

It has a couple more options, most of which handle with filtering the name or full (partial, i.e. below the current working directory) path, some of them case-insensitively (-iname and friends), and two global options, one to toggle regexp between POSIX Basic (default) and POSIX Extended, the other toggles symlinks (default on); this finds only files (and symlinks), not directories or submodules (“gitlinks”) by design.

It can also pass the file list to regular find(1) if it’s not too long (it must be passed on the command line), which allows for things like…

git find -- -mtime -100

… at slight filesystem cost (find does access the filesystem), but on the other hand, almost all (not search depth-specific stuff) of find works, and you only get to operate on files “in the index”, i.e. known to git (present in the HEAD commit or git added).

It’s a bit picky about unresolved conflicts though. If you notice any problems with it, just drop me a note (here, or via IRC).

PS: Feel free to lobby the official git people to subtree-merge the git-find repository, I’d be more than happy to have it integrated into git proper (the licence is even more liberal, you just need the mksh shell in a somewhat recent (50 should be sufficient) version, but it’s the most widespread Unix shell nowadays so that’s okay).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜