Shell – How to use a bash function like a regular command in a pipe chain

functionpipeshell-script

I'm performing several commands on large files from within a bash script. In order to monitor the progress I use the pv command.

An example command could look like this

cat $IN_FILE | pv -w 20 -s $(du -sb $IN_FILE | awk '{print $1}') | grep ...

The script contains multiple commands of similar structure, rather than having to use the same prefix on all of those commands over and over again I defined a function for the progress monitoring part as short hand. (Note: the fSize and fSize Sum functions wrap the du command part from the above example, where fSizeSum returns the sum of the size of two files fSize the size of one file):

function prog()
{
    local __size
    if [[ $2 ]]
    then
        __size=$(fSizeSum $1 $2)
    else
        __size=$(fSize $1)
    fi

    echo "cat $1 | pv -w 20 -s ${__size}"
}

Actually that approach already shortens the commands down a bit. I can execute the above example now like this:

eval "$(prog $IN_FILE) | grep ..."

What is still bothering me, is that I now have to quote each line and use eval. I'd rather like to use the function "prog" like it was a regular shell command i.e.:

prog $IN_FILE | grep ...

All my attempts to modify my function to work as a prefix in a chain of piped commands have failed so far.

Is there any way I can make self defined bash-script function to act like it was a regular bash command and put it in front of a pipe chain? If there is no way to do so using functions is there any other method to achieve this goal – like defining a local alias within the script?

Best Answer

In your function definition, I would suggest replacing:

echo "cat $1 | pv -w 20 -s ${__size}"

with just:

cat $1 | pv -w 20 -s ${__size}

This way, the function itself will execute this bit of code, without requiring a call to eval in the caller.