10

Let's say that I have a command git branch (always with a couple of words) for example.

What I want is to keep track of when this command is executed with arguments. For example, if I execute the command git branch develop without errors, I want to save develop on a file.

I tried to overwrite git command on my .bash_profile, something like this:

git () {
    if [ $# -eq 3 ]
    then
        git $@
        echo $2 > /path/tacked_parameters.txt
    else
        git $@
    fi
}

But seems that does not work well. Is there any way to do this?

jherran
  • 3,939
  • according to your example (git branch develop) you want to check if "$#" is "2" and not "3" ? ... (2 parameters to the git function) – Olivier Dulac May 12 '15 at 15:44
  • Was a mistake, but the code is just an example – jherran May 12 '15 at 15:46
  • ok. I added additional remarks underneath Stephane's (good) answer. my remarks may not be applicable (I think of the .txt as a log file, but it could be something else that can't have dates in it?) – Olivier Dulac May 12 '15 at 16:01

1 Answers1

18

You've got a few problems here:

  • your git function is calling itself recursively instead of the original git command.
  • you're using $@ unquoted which doesn't make any sense whatsoever
  • you're leaving other variables unquoted, asking the shell to split+glob them.
  • you're using echo for arbitrary data.
  • you're losing the exit status of the original git command.
  • you're overwriting your log file upon each invocation.
  • you're putting function definitions in your ~/.bash_profile which is meant to customize your login session, not your shell and is normally not read by non-login bash invocations.

You'd want something like:

git() {
  if [ "$#" -eq 3 ]
  then
    local ret
    command git "$@"; ret=$?
    printf '%s\n' "$2" >> /path/tacked_parameters.txt
    return "$ret"
  else
    command git "$@"
  fi
}

That is:

  • quote your variables,
  • use command to run the git command,
  • save the exit status of git in a local variables an return it on exit,
  • use >> instead of > for redirection to the log file.
  • use printf instead of echo.
  • and put that in your ~/.bashrc instead (making sure your ~/.bash_profile is sourcing ~/.bashrc as login bash shells don't read ~/.bashrc by default (a bash bug/misfeature)). Unless you want to export that git function (with export -f git) in case you also want bash scripts that call git to call that function.
  • 1
    Amazing explanation and works like a charm. Thank you very much. – jherran May 12 '15 at 12:35
  • +1 for a very good answer. But the op may need to change the check to [ "$#" -eq 2 ] , according to his example. And it could be a good idea to also add the date to "tacked_parameters.txt". And I'd go for the general case (ie, not just track of the 2nd parameters when 2 parameters, but track any parameters) : I'd get rid of the if, and have: printf '%s: %s\n' "$(date '+%Y-%m-%dT%H:%M:%S')" "$0 $*" ? (ie, show the command + all the parameters (note that you still lose some info, for example which parameter's had intra-separators, if any). Portable date close to the iso8601 standard) – Olivier Dulac May 12 '15 at 15:54