Search code examples
bashzshzsh-alias

trying to get a two bash functions with piping and optional args working


I have two things, one is a function the other is an alias and they don't quite work right.

The first is for tailing logs but only showing the first 3 lines by finding the important part of the log you're looking for and then showing the next two lines or however many you specify.

# tail -f $1 | grep $2 -A 2
function tinput() {
    if [ "$3" != "" ]
    then
        $(tail -f $1 | grep $2 -A $3)
    else
        $(tail -f $1 | grep $2 -A 2)
    fi
}

Lets say I use it like this:

tinput /var/log/webapps/app.name.com.error.log,#<.*Error:

It errors like this:

zsh: no such file or directory: .*Error:

I'm not sure but maybe it's not seeing the args properly or becuase I'm doing piping?

The second is:

function loadmysqldump() {
  $(pv $1 | mysql -u root $1)
}

It's for making mysql db dump recovery status a little more obvious (why programs don't use somthing to show that it's working I don't know, even a spinner would be nice) but not as obnoxious as doing -v.

Ok, so I admit to making a booboo, for some reason I forgot that args in the terminal are delimited by spaces, not apostrophes, so it does work; frankly I'm only using grep becuase I can't get what I actually want, the first n lines of each individual output from tail -f and nothing else I tried worked.


Solution

  • You can't (or shouldn't) call it like this:

    tinput /var/log/webapps/app.name.com.error.log,#<.*Error:
    

    The reason has to do with how zsh handles patterns that don't match anything. The presence of the unquoted * makes the entire first argument a pattern that zsh tries to match with existing files. When it doesn't match anything, it raises an error. You can change this behavior by unsetting the NOMATCH option, which will make zsh act like other shells and treat the pattern literally. A better solution is to be explicit and quote the argument:

    tinput "/var/log/webapps/app.name.com.error.log,#<.*Error:"
    

    In none of the cases above do you need command substitution.

    function loadmysqldump() {
      pv $1 | mysql -u root $1
    }
    
    function tinput() {
        if [ "$3" != "" ]
        then
            tail -f $1 | grep $2 -A $3
        else
            tail -f $1 | grep $2 -A 2
        fi
    }
    

    You can refactor tinput significantly to specify 2 as the default value for the -A option if $3 is empty or unset.

    function tinput() {
        tail -f $1 | grep $2 -A ${3:-2}
    }