23

I have following output from git status, how do I grep for everything after Untracked files:

[alexus@wcmisdlin02 Test]$ git status 
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   app/.gitignore
#   new file:   app/app.iml
#   new file:   app/build.gradle
#   new file:   app/proguard-rules.pro
#   new file:   app/src/androidTest/java/org/alexus/test/ApplicationTest.java
#   new file:   app/src/main/AndroidManifest.xml
#   new file:   app/src/main/java/org/alexus/test/MainActivity.java
#   new file:   app/src/main/res/layout/activity_main.xml
#   new file:   app/src/main/res/menu/menu_main.xml
#   new file:   app/src/main/res/mipmap-hdpi/ic_launcher.png
#   new file:   app/src/main/res/mipmap-mdpi/ic_launcher.png
#   new file:   app/src/main/res/mipmap-xhdpi/ic_launcher.png
#   new file:   app/src/main/res/mipmap-xxhdpi/ic_launcher.png
#   new file:   app/src/main/res/values-w820dp/dimens.xml
#   new file:   app/src/main/res/values/dimens.xml
#   new file:   app/src/main/res/values/strings.xml
#   new file:   app/src/main/res/values/styles.xml
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   .gitignore
#   .idea/
#   Test.iml
#   build.gradle
#   gradle.properties
#   gradle/
#   gradlew
#   gradlew.bat
#   settings.gradle
[alexus@wcmisdlin02 Test]$ 

Like this, but without specifying number of lines, like the -A parameter in GNU grep:

[alexus@wcmisdlin02 Test]$ git status | grep -A100 'Untracked files'
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   .gitignore
#   .idea/
#   Test.iml
#   build.gradle
#   gradle.properties
#   gradle/
#   gradlew
#   gradlew.bat
#   settings.gradle
[alexus@wcmisdlin02 Test]$ 

Is there a way to do it?

[alexus@wcmisdlin02 Test]$ grep --version
grep (GNU grep) 2.20
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
[alexus@wcmisdlin02 Test]$ 
alexus
  • 13,667

6 Answers6

27

With GNU grep (tested with version 2.6.3):

git status | grep -Pzo '.*Untracked files(.*\n)*'

Uses -P for perl regular expressions, -z to also match newline with \n and -o to only print what matches the pattern.

The regex explained:

First we match any character (.) zero or multiple times (*) until an occurence of the string Untracked files. Now, the part inside the brackets (.*\n) matches any character except a newline (.) zero or multiple times (*) followed by a newline (\n). And all that (that's inside the backets) can occure zero or multiple times; that's the meaning of the last *. It should now match all other lines, after the first occurence of Untracked files.

chaos
  • 1,565
18

If you don't mind using sed, here is a possible solution

git status | sed -n -e '/Untracked files/,$p'
rahul
  • 281
10

I would use awk for this:

git status | awk '/Untracked files/,0'

This /Untracked files/,0 is a range exression. It evaluates to True from the first time Untracked files and until 0 evaluates to True. Since this never happens, it prints the rest of the file.

Note that awk's behaviour to a True is to print the current record (line, normally), that's why we don't have to explicitly call print.

fedorqui
  • 278
3

You may try:

git status | grep -A99 Untracked

where -A would print lines of trailing context after the match.

Alternatively use more or less, for example:

git status | less +/Untracked

For scripting purposes, I'd use ex/vi:

git status | ex -s +"/Untracked/norm d1G" +%p -cq! /dev/stdin

To include line with Untracked files, use kd1G instead of d1G.

Or without piping and /dev/stdin, the syntax would be: ex ... <(git status).

kenorb
  • 7,125
1

For a one-liner with parenthesis to spawn a subshell so you avoid retaining the variables:

(while read LINE ; do [[ "$LINE" =~ "Untracked files" ]] && MATCHED=1 ; \
   [[ "$MATCHED" = 1 ]] && echo "$LINE" ; done < <(git status))

You can just pipe at the end of that into whatever else you need to do with it.

Or you can use it in whatever shell script

while read LINE ; do
    [[ "$LINE" =~ "Untracked files" ]] && MATCHED=1
    [[ "$MATCHED" = 1 ]] && echo "$LINE"
done < <(git status)

Replace the echo "$LINE" with whatever you want to do with the data. If you want to skip the "Untracked files" line, then just switch the two tests.

Hyppy
  • 15,814
0

you can use something like this, I used Perl, the following command set count = 1 if I match some string in the current line and when the while loop is finished I check the count variables and I print the range of lines from where match happen to the last line

ls -al | perl -e '@LINES = (); $n = 0 ; $nline = 0; while(<>){ push(@LINES, $_); $n++; if($_ =~ m/mirror/i) { $count = 1; $nline = $. - 1 };};  if($count != 0){ foreach $i($nline..$n-1){ print "\t$LINES[$i]\n";}}'
c4f4t0r
  • 5,491