Alias: extract options from command

aliasbashbashrc

Apologies for the bad title. I couldn't come up with a better one.

I want to alias a command to another command, and extract options from the text of the command itself. I realize this is unclear, so perhaps an example will help:

If i were to do something like this with ls, I would want to be able to alias the following:

ll -> ls -l
la -> ls -a
lal -> ls -al
l -> ls

BUT

ls -> ls #allow this special case to not change

preferably, I would like to be abel to determine on my own whether to igrone part of the command, like I do with the s in ls. so, for example, I'd also like to be able to do with grep:

grepi -> grep -i
greps -> grep -s
grepis -> grep -is

we dont have to worry right now about options that take arguments, for example, its ok if grepm fails.

Best Answer

You can do this using the following:

  • Set shopt extdebug, enabling several debug options. The relevant one is: If the command run by the DEBUG trap returns a non-zero value, the next command is skipped and not executed. We need this to not actually try to execute the undefined lal command.
  • A trap for the DEBUG signal, which is executed before any command is executed. Set the trap like this: trap 'insane_magic_alias' DEBUG.

The function insane_magic_alias parses the command about to be executed (in $BASH_COMMAND) and processes it, aborting execution of the actually entered command in the process by return 1, unless type says it exists, in that case we do nothing (and let it run).

# make sure to name this function appropriately...
function insane_magic_alias {
    local CMD=$BASH_COMMAND

    # make sure this isn't a command that exists
    if ! type "$( echo "$CMD" | awk -F' ' '{ print $1 }' )" >/dev/null 2>&1 ; then

        # handle calls to `l*`
        if [[ ${#CMD} -gt 1 && "${CMD:0:1}" = l ]] ; then
            # actual transformed program call
            ls -${CMD:1}

            # abort execution of undefined command
            return 1
        fi
    fi
    # either execute an existing command, or show the "command not found" message
    return 0
}

Result:

$ lal
total 0
drwxr-xr-x   2 danielbeck  staff    68  2 Aug 22:53 .
drwxr-xr-x@ 78 danielbeck  staff  2652  2 Aug 22:53 ..

Note that your bash thinks you have a job running for a moment just afterwards (if you print job information in your PROMPT_COMMAND, you will notice this). Plus probably another few side effects that make this fail in any case not just a simple demo...

Related Question