8

Here's my .zshrc:

alias inst="adb install -r -d"

notify() {
  start=$(date +%s)
  "$@"
  notify-send "\"$(echo $@)\" took $(($(date +%s) - start)) seconds to finish"
}

When I run the command notify inst app.apk, I get an error:

notify:2: command not found: inst
  0.00s user 0.00s system 0% cpu 0.001 total

Can anyone shed some light on why this doesn't work, and hopefully a way to make it work?

Caleb Jares
  • 6,163
  • 6
  • 56
  • 83

2 Answers2

5

When the shell processes commands, among other things (e.g. PATH search) it will check to see if the first token/argument (whitespace delimited) belongs to an alias loaded in the current environment. If the alias you are trying to substitute is not the first token, the substitution will not happen. If your alias happens to not be the name of an executable on the PATH or current directory, the error will propagate back up to a command not found.

Since your question is about the Z Shell, zsh actually provides a lesser-known feature called global aliasing. If an alias is declared with the -g flag, zsh will make the appropriate substitution for not only the first token, but any token, regardless of order.

alias -g inst="adb install -r -d" should do the trick.

Keep in mind that this is a zsh only feature for portability reasons, and make sure that whatever script your writing has a shebang line that invokes the zsh shell: #!/usr/bin/env zsh

I would also recommend to not use zsh global aliasing in important or production scripts. For personal use, it is perfectly fine.

JoshuaRLi
  • 1,665
  • 14
  • 23
1

Don't use alias for scripting

First, according to the advanced bash scripting guide:

In a script, aliases have very limited usefulness.

So you may consider not using alias but a function for instance (still from the same page, 2 paragraph lower):

Almost invariably, whatever we would like an alias to do could be accomplished much more effectively with a function.

A hacky solution

If this is for a quick script for yourself using aliases you have in your .zshrc, there is still a way out.

alias foo='echo hello'

bar() {
    `alias "$@" | cut -d\' -f2`
}

bar foo # => hello

Alias replacement

from alias man page:

The first word of each simple command, if unquoted, is checked to see if it has an alias. If so, that word is replaced by the text of the alias. The alias name and the replacement text can contain any valid shell input, including shell metacharacters, with the exception that the alias name can not contain `='.

The first word of the replacement text is tested for aliases, but a word that is identical to an alias being expanded is not expanded a second time. This means that one can alias ls to "ls -F", for instance, and Bash does not try to recursively expand the replacement text.

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt .

The rules concerning the definition and use of aliases are somewhat confusing. Bash always reads at least one complete line of input before executing any of the commands on that line. Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias. This behavior is also an issue when functions are executed. Aliases are expanded when a function definition is read, not when the function is executed, because a function definition is itself a compound command. As a consequence, aliases defined in a function are not available until after that function is executed. To be safe, always put alias definitions on a separate line, and do not use alias in compound commands.

Community
  • 1
  • 1
Ulysse BN
  • 10,116
  • 7
  • 54
  • 82
  • 1
    The question is about zsh, not bash. Since zsh is a feature superset of bash, you miss some things by citing bash documentation in your answer. – JoshuaRLi Aug 09 '17 at 23:10
  • This still looks pretty accurate to me. Do you find something not applicable to `zsh` in my quotes ? Still I just saw your solution, and like it for the brilliant global alias idea, which use indeed the fact that zsh is a superset! But to answer OP, still using a normal alias, I still consider my answer accurate – Ulysse BN Aug 09 '17 at 23:14