Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

In my .profile (sourced in sh emulation mode from my .zshrc) I have the following snippet:

if [ -f /usr/bin/pacmatic ]; then
    alias pacman=pacmatic
fi

# Colorized Pacman output
alias pacman="pacman --color auto"

However, the second alias always overrides the first:

% type pacman
pacman is an alias for pacman --color auto

How can I make it so that the second alias assignment "inherits" the first assignment, so that if /usr/bin/pacmatic exists, the alias becomes pacmatic --color auto?

I'm not averse to using functions instead of aliases, but I'd prefer it if the logic wasn't performed every time pacman is invoked (I want pacmatic checked for once, at shell startup, not every time pacman is run). I'd also prefer an sh-portable script, but if this isn't possible, you can use full zsh syntax.

(Yes, I'm aware that this could easily be solved by appending --color auto to the pacmatic alias. But I want to do it the Right Way™.)

I've tried Googling and looking through the manpages, but to no avail.

share|improve this question
    
I thought the Right Way was to use functions instead of aliases. I've heard that they're faster than aliases (at least in bash), and they can easily call each other. –  Wutaz Apr 13 at 15:37

5 Answers 5

up vote 3 down vote accepted

A shell alias behaves pretty similarly to a #define, i.e. redefining a shell alias would override the previous one.

I'm not sure what would be the Right WayTM, but one approach would be making use a shell function that accepts parameters and using that to create an alias. Your code snippet could be rewritten as:

if [ -f /usr/bin/pacmatic ]; then
    pacman() { pacmatic "$@"; }
fi

# Colorized Pacman output
alias pacman="pacman --color auto"

 


Moreover, even if you were using different aliases and were trying to use one for defining the other, it would not work as aliases are not expanded in non-interactive mode by default. You need to enable it by setting expand_aliases:

shopt -s expand_aliases

Quoting from the manual:

   Aliases are not expanded when the shell is not interactive, unless  the
   expand_aliases  shell option is set using shopt (see the description of
   shopt under SHELL BUILTIN COMMANDS below).
share|improve this answer
    
this appears to be the closest to what I want, but it doesn't work. type pacman returns pacman is an alias for pacman --color auto, both in sh emulation mode and in native zsh mode. however, looks like the edit you just made is what I need. –  strugee Apr 14 at 2:49
    
FWIW, the zsh equivalent is setopt aliases. –  strugee Apr 14 at 3:00
    
OP is using zsh. And the shell appears to be interactive anyway. –  Mikel Apr 14 at 19:15

Alias substitution is only performed when reading lines from interactive sources. So the second alias is not affected by the first, hence the literal replacement.

Perhaps something similar:

PACMAN=pacman
if [ -f /usr/bin/pacmatic ]; then
    PACMAN=pacmatic
fi

# Colorized Pacman output
alias pacman="${PACMAN} --color auto"

This'll set 'pacman' to the proper value, the PACMAN env variable is not exported, so it'll go away when the script finishes, and using "double quotes" will ensure that variable substitution occurs at the declaration of the alias, not for each invocation.

I use a similar method:

PACMAN=pacman
which pacmatic &>/dev/null && PACMAN=pacmatic
alias pacman="${PACMAN} --color auto"

Basically, set the env var PACMAN, test for pacmatic in path, if found, set PACMAN, then define alias.

Hmm, you could optimize a bit more...

which pacmatic &>/dev/null && PACMAN=pacmatic
alias pacman="${PACMAN:-pacman} --color auto"

Taa Daa! Set to 'pacman' if PACMAN is unset or null, otherwise, set to value of PACMAN, set to pacmatic by the 'which' line.

share|improve this answer
    
Why would aliases only work for "interactive sources"? –  Mikel Apr 14 at 2:37
    
You're right that by default, bash doesn't expand aliases in non-interactive mode, but how is that the same as "interactive sources"? –  Mikel Apr 14 at 3:09
pacman() ( def_args="--color auto" bin=
    [ -x ${bin:=/usr/bin/pacmatic} ] || bin=
    [ -x ${bin:=/usr/bin/pacman} ] || bin= 
    ${bin:?WHERE THE HELL IS PACMAN????} \
        $def_args "$@"
)

Aliases are for the birds.

share|improve this answer

In zsh, you can easily append to an alias by using the aliases associative array:

alias pacman="${aliases[pacman]-pacman} --color auto"

In other shells, you need to use the output of the alias command to find out about existing aliases.

current_pacman_alias=$(alias pacman 2>/dev/null)
alias pacman="${current_pacman_alias:-pacman} --color auto"

While I'm offering this as a possibility, I'd go with using a variable as already suggested by other answers. It's clearer, and you can discriminate on the value of the variable if you want to configure some things differently based on which one of pacmatic or pacman is in use.

pacman==pacmatic 2>/dev/null || pacman=pacman
alias pacman='$pacman --color auto'
share|improve this answer

A short version for the 2nd alias would be:

alias pacman=$PACMAN' --color auto'
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.