0

Somehow related to this other question (actually, the opposite). I would like to get a report like this:

dir1 : 2 files modified, 3 deleted, 2 sub-dirs modified
dir2 : 7 files modified, 2 added, 7 deleted

Where dir1 and dir2 are direct children of the current directory. The report would not be recursive, just applied to the current directory.

Can git status provide such a report?

Community
  • 1
  • 1
blueFast
  • 41,341
  • 63
  • 198
  • 344
  • Sure it can, provided git only controls the content of the directory in question. Otherwise you have to filter modifications shown for recursively traveled directories. Since the suggested format is not a git native format you have to convert its output, though. – arkascha Mar 18 '15 at 16:37
  • You received a lot of suggestions on the other question. Go read the `git` manual, the manual pages of the Unix tools used in the answers provided there and find yourself the best way to get what you need. – axiac Mar 18 '15 at 18:02
  • @axiac: I (mostly) know git, I know about the other tools. I just do not want to reinvent the wheel, in case there is an obscure git subcommand which does something similar to what I am looking for. – blueFast Mar 18 '15 at 18:44
  • How "obscure" is a command depends a lot on your level of `git` knowledge. `git status -s` was an obscure option for me until today. Btw, processing its output with several shell commands can produce almost all the numbers you want (I'm not sure how to get the `2 sub-dirs` part). – axiac Mar 18 '15 at 18:53
  • 1
    Getting the modified sub-dirs is actually more complex, since git is mostly file-oriented, but it is actually not that important. The answer by @Jubobs is good enough for my use case. Not sure if all corner cases are covered; I will find out in due time ... – blueFast Mar 18 '15 at 18:59

2 Answers2

1

With git diff --name-status or git status --porcelain you can get a list of all files which have changed and how. Then you can format it however you like.

git status --porcelain will give you a complete status regardless of whether the changes are indexed or not, just like git status.

git diff --name-status will act like normal git diff and only give you changes relative to the index. Run an extra --staged to get the complete view.

Here's an example.

$ git st
On branch Kavorka
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    META.json

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   lib/Method/Signatures.pm
    modified:   t/array_param.t
    modified:   t/examples/silly.t

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    t/lib/Errors.pm

$ git diff --name-status
M   lib/Method/Signatures.pm
M   t/array_param.t
M   t/examples/silly.t

$ git diff --name-status --staged
D   META.json

$ git status --porcelain
D  META.json
 M lib/Method/Signatures.pm
 M t/array_param.t
 M t/examples/silly.t
?? t/lib/Errors.pm
Schwern
  • 153,029
  • 25
  • 195
  • 336
1

Shell script

What follows isn't a full solution, but it's a start. A more efficient and robust approach would use awk instead of sed to compute the three counts in only one pass over the output of git status --porcelain.

#!/bin/sh

# git-status-perdir.sh
#
#      Reports the numbers of modified, added, and deleted files in each
#      subdirectory of the current directory

for f in *; do
    if [ -d "$f" ]; then                     # if f is a directory...
        out=$(git status --porcelain -- $f)
        mod=$(printf "$out" | grep -c '^ M') # count modified
        add=$(printf "$out" | grep -c '^A')  # count added
        del=$(printf "$out" | grep -c '^D')  # count deleted
        printf "%s : %d modified, %d added, %d deleted\n" \
            "$f" "$mod" "$add" "$del"
     fi
done

Toy example

# set things up
$ mkdir testgit
$ cd testgit/
$ git init

# create dir1, dir1/foo1.txt and dir1/bar1.txt
$ mkdir dir1
$ touch dir1/foo1.txt
$ touch dir1/bar1.txt

# stage all and commit
$ git add .
$ git commit -m "add foo1 and bar1"

# create and stage dir2 and dir2/foo2.txt
$ mkdir dir2
$ touch dir2/foo2.txt
$ git add test2/

# remove the (tracked) file dir1/foo1.txt
$ git rm dir1/foo1.txt

# modify dir1/bar1.txt
$ printf "Hello, world\n" > dir1/bar1.text

# run the script
$ sh git-status-perdir.sh
dir1 : 1 modified, 0 added, 1 deleted
dir2 : 0 modified, 1 added, 0 deleted
jub0bs
  • 60,866
  • 25
  • 183
  • 186