Search code examples
gitshellsedmsysgithead

make head stop waiting for input


I'm developing "custom grep" wrapper for git. It shows first line of the file matching pattern. This line expected to be the header of the file.

I've created alias and everything went OK, until I tried search for pattern, which cannot be found in the working folder. Since no files were found, head and sed commands has nothing to work with and command hands and waits for input.

How to prevent this? I would like script to interrupt if no input is given. Definitely I could create separate script, assign list of files to variable and check length of this variable. But I would prefer sweet & neat oneliner-alias.

Is it possible? Here is my .gitconfig alias section:

[alias] 
    gg = !sh -c 'head -n1 -q `git grep --name-only $0` | sed s/OBJECT.//'

Resolution

Following commands for aliases worked for me on Windows 7 x64, msysGit 1.7.11.1:

gg = !sh -c 'head -n1 -q `git grep --name-only $0` < /dev/null | sed s/OBJECT.//' 

and

gg = !sh -c 'git grep --name-only $0 | xargs -l sed -n "1{s/OBJECT.//p}"'

But performance was different. The first approach is noticeably more fast.


Solution

  • To address your immediate question on how to prevent head from stalling waiting for non-existent input, you can to use process substitution instead of command substitution:

    head -n1 -q <(git grep --name-only $0) | sed s/OBJECT.//
    

    Unlike command substitution where the ```cmd`` portion is replace by the output of the command, with process substitution the<(cmd)` portion is replace by a filename of a file/pipe that contains the output of the command.

    In the event where the command output is empty, head will still receive an input i.e. the filename of an empty file/pipe, and will proceed as you'd expect.

    P.S. note that you will need to use bash instead of sh in order to use process substitution.

    Update

    If your version of bash does not support process substitution, another way to get round the issue would be to redirect in contents from an empty or dummy file:

    head -n1 -q `git grep --name-only $0` < /dev/null | sed s/OBJECT.//
    

    Alternatively, you could simply pipe the output of git grep to xargs which allows you to then chain in calls to head or sed as shown in patthoyts answer.