6

I have a folder, /c/Tools, with three folders.

I want a command like below

$ ls --show-repositories

Tools is NOT a git repository, but Tools/MyProject and Tools/MyApp both are. The output I want is:

drwxr-xr-x 1 0018121 Domain Users    0 Dec 14 14:33 MyProject/ (develop)
drwxr-xr-x 1 0018121 Domain Users    0 Dec 14 14:17 Data/
drwxr-xr-x 1 0018121 Domain Users    0 Dec 14 12:08 MyApp/ (master)
-rw-r--r-- 1 0018121 Domain Users 399K Aug  4 10:41 readme.txt
-rw-r--r-- 1 0018121 Domain Users 136K Aug  4 10:20 image.jpg

so from the parent folder I can tell if a child folder is a current valid git repository (and what branch is currently checked out)

Thanks

2
  • or even better, since i think i can figure this out somewhat is how to get GIT to NOT print errors. i call cur=$(git symbolic-ref -q --short HEAD>&1); but if the current folder isn't a repository it echos the "fatal:..." message. I'm trapping the result through $? so i don't WANT that message reported, since I am intentionally using the command to determine if the current folder is a repository. Dec 14 '15 at 20:54
  • 1
    You can eat stderr with 2> /dev/null.
    – DopeGhoti
    Dec 14 '15 at 21:01
5

Keep it simple; look for the directory .git and run your commands from within its containing directory. Also throw in a -print to see what dir it is running in:

find . -type d -name .git -print -execdir git symbolic-ref --short HEAD \;

(Okay, actually -print shows the dir it found./path/to/repo/.git, not the ./path/to/repo/ itself. But that's a minor inconvenience.)


EDIT: You can produce the EXACT output requested in your OP by the following:

paste <(ls -ld *) <(for i in *; do if [ -d "$i"/.git ] ; then echo "($(git --git-dir="$i"/.git symbolic-ref --short HEAD))"; else echo; fi; done)

This doesn't have any real drawback that I can see.

By design it only finds top level git repos, i.e. if your "Data" directory (in your example ls output) has subdirectories which are git repos they won't be listed, whereas with the find command I gave earlier they would be. But as I say that's by design.

This doesn't preserve colors in the output of ls. You can do this by adding a --color=always to the embedded ls command:

paste <(ls -ld --color=always *) <(for i in *; do if [ -d "$i"/.git ] ; then echo "($(git --git-dir="$i"/.git symbolic-ref --short HEAD))"; else echo; fi; done)

Though, for some reason, this produces an extra newline at the end of all the output. Oh well; not a big deal IMO.


For Mac OS, ls doesn't have a --color flag, so use the following to force color output:

paste <(CLICOLOR_FORCE=true ls -ld *) <(for i in *; do if [ -d "$i"/.git ] ; then echo "($(git --git-dir="$i"/.git symbolic-ref --short HEAD))"; else echo; fi; done)
1
  • (I explored doing the whole thing in a for i in * loop, but then the formatting for ls -ld doesn't line up as the output for each file is formatted separately.)
    – Wildcard
    Dec 15 '15 at 2:06
0

May be something like that:

find YOUR_DIR -maxdepth 1 -type d -exec echo -n "{}  " \; -exec git --git-dir={}/.git symbolic-ref -q --short HEAD \;

Example output:

.  fatal: Not a git repository: './.git'
./zabbix2  master
./dnsmasq  fatal: Not a git repository: './dnsmasq/.git'
./puppet-network  master
./resolv_conf  fatal: Not a git repository: './resolv_conf/.git'
./old  fatal: Not a git repository: './old/.git'
./php_ini  fatal: Not a git repository: './php_ini/.git'
./stdlib  fatal: Not a git repository: './stdlib/.git'
./mcollective  master
./netlogon  master
./debian  master
./apt  fatal: Not a git repository: './apt/.git'

You can play with first 'exec' command to change needed folder output format.

0

Well,

I will say I that "--git-dir" option was new to me and that did the trick. Now for the fun part. Here is my complete answer, which is a combination of other queries here. If anyone knows a way to speed this up, that would be excellent.

alias ls='ls -FHlAt --color --show-control-chars --group-directories-first'
alias lsdif='ls | xargs --delimiter="\n" ~/.config/lsdif_colors.sh'

#################
# lsdif_colors.sh
#################
for fileLine in "$@"
do
    if [[ $fileLine == total* ]]; then echo $fileLine;
    else 
        cols=($fileLine);

        cw=(-10 -1 -7 -6 -5 4 -3 2 -5 0);               
        for ((i=0 ; i < 9; i++))
        do
            printf "%${cw[i]}s " ${cols[i]}
        done

        name=${cols[@]:9}
        if [[ -d .git ]]; then 
            difType=$(git diff --name-status ./$name)
            if [[ ${difType:0:1} = "M" ]]; then printf "%1s \e[34m%s\e[0m\n" ${difType:0:1} "$name"
            elif [[ ${difType:0:1} = "D" ]]; then printf "%1s \e[31m%s\e[0m\n" ${difType:0:1} "$name"
            elif [[ ${difType:0:1} = "A" ]]; then printf "%1s \e[32m%s\e[0m\n" ${difType:0:1} "$name"
            else printf "   %s\n" "$name"
            fi;
        elif [[ $fileLine == d* ]]; then 
            d=$(echo ${name:0:((${#name}-1))} | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")
            branch=""
            if [[ -d $d/.git ]]; then 
                branch="("$(git --git-dir="$d"/.git symbolic-ref -q --short HEAD>&1)")"
            fi;
            printf "   %s \e[36m%s\e[0m\n" "$name" "$branch"
        else printf "   %s\n" "$name"
        fi;     
    fi;
done 

this allows me to see a general view of a directory with one command, however, it does go a little slow. I'm not expecting the same speed as ls, but lsdif is choppy. if it can be sped up, great. if not, shrug oh well.

Thanks Jaeden "Sifo Dyas" al'Raec Ruiner

2
  • Re "If anyone knows a way to speed this up...": What does this script do that my paste one-liner doesn't? The paste command (a) is very very fast and (b) produces the exact output requested in your question.
    – Wildcard
    Dec 15 '15 at 16:29
  • @Wildcard if you notice that this function is not the exact output of my question. My question was only a part of this output, as this script also prints out the git diff status for files, so i can see in one command, which folders are repositories, and if i'm in a repository, which items have been altered. my next phase will be to add an unstaged check to this script so I can see those as well. Dec 15 '15 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.