7

I want to use different aliases (or perhaps: the same alias differently) depending on the current working directory. For example, I might want to use l as a shorthand for ls with some extra options. I want to use two variants:

alias l="ls --sort=extension" # variant A
alias l="ls --quoting-style=literal" # variant B

Normally, I would like to use variant A. However, I want to use variant B when listing pictures – that is, when my working directory is ~/pictures. (This is merely a minimal example. My actual use case is more complicated.)

I am aware that I could simply write a function l() with a case differentiation on the output of $(pwd). However, I want a more robust solution which allows me to rename the specific directories without changing any alias (and that doesn’t clutter my .zshrc).

But is it possible to overwrite or add aliases, e.g. by setting up a local .zshrc within the relevant directory (like it is possible for vim and a local .vimrc)?

Furthermore, is it (also) possible in bash or any other shell?

1
  • 1
    I'm sure zsh has similiar functionality, but another route could be to hook into 'cd' (or prompt_command) and run a function that overwrites aliases as needed.
    – Jeff Schaller
    Commented Jul 5, 2017 at 15:55

5 Answers 5

4

If you are using oh my zsh, just activate the dotenv plugin:

plugins+=(dotenv)
ZSH_DOTENV_FILE=.any-name-you-like-for-the-per-directory-alias-file

Also consider direnv, which lets you export environment variables in a per-directory .envrc, and unset them when you move away (which dotenv cannot do). direnv is compatible with all the popular shells. However, it doesn't currently let you define aliases or functions.

You can still combine ilkkachu's approach with direnv, by creating a function (rather than an alias) that decides what to do based on one (or several) environment variables, which are in turn set by direnv.

Both approaches deal with the security aspect by having you manually whitelist directories in which the dot files will be sourced.

4
  • 1
    sounds even worse from a security standpoint than Microsoft's infamous AUTORUN. Commented Jun 10, 2020 at 9:45
  • @StéphaneChazelas Can you elaborate or provide a reference?
    – k.stm
    Commented Jun 27, 2020 at 21:38
  • @k.stm, I mean running arbitrary code stored in any of the directories you traverse could be abused the same way autoruns were abused to spread malware on Microsoft systems. I can see now that dotenv seems to allow some form of whitelisting which would mitigate the risk somewhat, but that's still risky, in that if one day you allow /media/cdrom or /tmp/something for instance, you leave a door open for abuse in the future. Commented Jun 28, 2020 at 6:55
  • @StéphaneChazelas Yes, thanks for the explanation! I don’t think the hazard is too great though when using whitelisting.
    – k.stm
    Commented Jun 28, 2020 at 15:23
4

You could create a function or a script to check some file in the current directory and change behaviour based on that:

l() {
    if [ -f ./.ls-literal-quote ] ; then
         ls --quoting-style=literal "$@"
    else
         ls --sort=extension "$@"
    fi
}

Something like that would allow you to keep the configuration in the directory itself, instead of some centralized location if that's what you want.

Now, that requires littering the involved directories with extra files, but you might be able to work around that by using extended attributes (if your system supports that).

1
  • Yes, that would work. But with a lot of such local deviations of aliases, that method would quickly clutter my .zshrc and become less manageable. Anyway, that would work. (Thanks!)
    – k.stm
    Commented Jul 5, 2017 at 15:57
2

I'm working on a project that accomplishes just that. Check it out: localalias.

It allows you to create and use pseudo-aliases and functions that are local to the directory they are defined in. Perhaps the best part is that it accomplishes this without performing any dicey "source" commands. These solutions are easier and faster, but are a big security concern.

Here's a demo:

enter image description here

2
  • When evaluating an otherwise invalid command, are global aliases checked before local aliases? It would be nice to have local aliases take priority. (And maybe even before valid commands themselves, but this may be risky I guess …)
    – k.stm
    Commented Jan 6, 2018 at 15:07
  • 1
    You could make it work that way by redefining chpwd as mentioned in this article. Add a conditional check for $(pwd)/.lshrc. If found, source it. Otherwise, source zshrc. This is less secure. My real problem with this method, however, is that it pollutes the namespace, making it hard to know which aliases are defined at any given moment. You can use unalias -a at the top of your zshrc to reduce this pollution, but I don't think there is an equivalent command for function definitions. Commented Jan 7, 2018 at 3:37
1

If you want a clean alias that is robust, complex, and extensible, the first option that comes to mind is creating a bona-fide script (e. g. l) that you keep in ~/bin. You could then either add this directory to your PATH or create an alias which explicitly calls it for you.

2
  • I don’t quite get this: What would be the contents of such a script – the same as that of zsh function l() in .zshrc solving the problem? If I was to rename the relevant directory, e.g. $ mv ~/pictures ~/videos, would I have to adapt the script you are talking about?
    – k.stm
    Commented Jul 5, 2017 at 15:48
  • Yes, you would have to keep the script up to date for your use-case, but maintaining such a script is more tenable than maintaining an alias. You could changes ls's behavior in a simple case $(pwd | sed 's_^.*/__') stanza.
    – DopeGhoti
    Commented Jul 5, 2017 at 16:17
0

Sure; just make the alias expand to some shell code that does the test for you:

alias l="[[ $PWD =~ /pictures$ ]] && ls --quoting-style=literal || ls --sort=extension"
4
  • Then I would still have to change the alias when renaming ~/pictures to ~/videos.
    – k.stm
    Commented Jul 5, 2017 at 15:51
  • extend the [[ to be a case statement, if you have other variations you want to use
    – Jeff Schaller
    Commented Jul 5, 2017 at 15:51
  • how would the alias know what to do if you rename a folder? I think you'd have to tell it ahead of time.
    – Jeff Schaller
    Commented Jul 5, 2017 at 15:51
  • As I said, I want to add or overwrite existing aliases depending on the current working directory. So this would have to take advantage of some (maybe nonexisting) feature of zsh interpreting aliases differently depending on some context.
    – k.stm
    Commented Jul 5, 2017 at 15:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .