Find the location of an alias definition

aliaszsh

I can find the location of a function definition, but this doesn't work for aliases:

$ type -a subl

subl is an alias for /Applications/Sublime\ Text\ 2.app/Contents/SharedSupport/bin/subl
subl is /Users/brandon/bin/subl

I want to know where that alias is defined, not what it is defined as, or where it points. In other words: if I want to change it, what is the file and line number to go to. I've searched my .zshrc and the directories in which I keep files that it sources, and I'm finding nothing1. How can I find it without having to search manually?


1. I did eventually find it by running zsh -v and searching for subl, and then reading upward until I found a line that started with source. Nonetheless, I'd like a non-manual way of doing this in the future.

Best Answer

Solution

This should do the trick:

PS4='+%x:%I>' zsh -i -x -c '' |& grep subl

This should print something like

+/Users/brandon/.zshrc.d/aliases.zsh:32>alias 'subl=/Applications/Sublime\ Text\ 2.app/Contents/SharedSupport/bin/subl'

Meaning that in file /Users/brandon/.zshrc.d/aliases.zsh (just for example) on line 32 the command alias 'subl=/Applications/Sublime\ Text\ 2.app/Contents/SharedSupport/bin/subl' was executed. Note that the shown command line is the result of parsing the command written in the file, as such they might not be indentical.


Explanation

The configuration of zsh is essentially a list of shell commands. The information from where a command was run is usually only available at the time the command actually runs. Once the command finishes any changes in the environment or shell settings may remain, but the information how these changes came to be is gone. So searching the configuration files or tracing the information during runtime are the only options.

Searching the configuration files is - as you noticed - prone to errors, as it is easy to overlook some configuration files; zsh directly loads up to eight different configuration files when starting an interactive shell and any number of additional files may be sourced from there.

This is where zsh's XTRACE (-x) comes into play. Similar to VERBOSE (-v) XTRACE prints the command lines that are executed, but it also precedes each line with the PS4 prompt. PS4 can be configured to show the file and line number currently executed. (By default PS4 shows the name of the function or script file and the number of the currently executed line. So, should a line of code be inside a function, it would not immediately show where it is defined.).

In details the above command does the following:

  • Set the environment variable PS4 to +%x:%I> (for this command only). %x is replaced by the name of the file containing the source code currently being run. %I is the line number of that code within the file. + and > are decoration to differentiate XTRACE output from any output the script might generate.

    Note: This may not work correctly, if PS4 is set to a different value somewhere in the configuration. Should the output not have the desired format, it may be necessary to first remove/comment out the PS4 or PROMPT4 settings.

  • zsh starts zsh

    • with interactive mode enabled (-i)
    • with XTRACE enabled (-x)
    • and just runs an empty command line (-c ''), immediately exiting thereafter.

    That means, that only the initialization files for interactive mode are run and there is no clutter from prompt generation or hook commands.

  • |& is a shorthand for 2>&1 |, which connects the standard output and the standard error of one command to the standard input of the next.
  • grep subl searches for "subl". I suggest looking just for the name of the alias, as the exact command line might not be alias subl="..." due to parsing. (In zsh you could even define an alias without using the alias command by assigning key-value-pairs in the assoziative array aliases: aliases[subl]="...")
Related Question