28

Suppose you have an alias go, but want it to do different things in different directories?

In one directory it should run cmd1, but in another directory it should run cmd2

By the way, I have an aliases for switching to the above directories already, so is it possible to append the go alias assignment to the foo alias?

alias "foo=cd /path/to/foo"

Working in bash(?) on OSX.

1
  • 3
    This is what makefiles are for.
    – itsbruce
    Commented Oct 29, 2012 at 14:41

8 Answers 8

19

It is not completely sure what you are asking, but an alias just expands to what is in the alias. If you have two aliases, you can append the different commands, even aliases.

alias "foo=cd /path/to/foo; go"
alias "foo2=cd /path/to/foo2; go"

In any other situation, you could specify a function in your .bashrc

function go ()
{
    if [ "$PWD" == "/path/to/foo" ]; then
       cmd1
    elif [ "$PWD" == "/path/to/go" ]; then
       cmd2
    fi;
}

In case you have more choices, you could better use a case structure.

8

If you add the following function to your .bashrc

function cd () { 
  builtin cd "$@" && [[ -f .aliases ]] && . .aliases
  return 0
}

Every time you cd to a directory with an .aliases file it will get sourced.

Careful with security if others can create files on your machine.

With this trick aliases never get removed but you can write as much code as you like in the function.

ondir uses this trick and has a ton of bells and whistles.

http://swapoff.org/ondir.html#download

3
  • While I think this is clever it seems it is dangerous since it relies on .bashrc. (This won't work for cron, for instance).
    – ctbrown
    Commented Dec 21, 2017 at 17:30
  • 1
    I'm not sure there is anything dangerous about bashrc. I believe that this is the standard/correct place for aliases. It is in the nature of environments that they are different. Give the question, a different environment is what is required. Nothing to stop you sourcing a users .bashrc in cron if you want cron to have a similar environment. N.B. cron should always be expected to behave differently to an interactive shell due to use of isatty and chums.
    – teknopaul
    Commented Dec 23, 2017 at 22:52
  • True, there is nothing dangerous about bashrc itself. The problem is that you have no way of ensuring that the process that is changing to directory will source bashrc. It is one thing if it is your interactive session. It is quite another if that directory is shared among users and processes which may or may not use the bash shell. .bash_aliases is the preferred location for bash aliases on some systems.
    – ctbrown
    Commented Dec 25, 2017 at 15:55
5

I get the feeling you are very "directory oriented", and, in that case, this might suite your mentality better.

(But to be honest, I think this is a bad idea altogether, you'd like commands to be global.)

In .bashrc, put alias go="./.cmd" (then source ~/.bashrc).

Then, in each such directory, put a script called .cmd, then chmod +x .cmd, then just go do your thing.

2
  • 2
    That's a lot of work...here's the use case: When running tests, I want to alias rspec-all to run certain tests. But which tests depends on the project. And that is determined by the directory.
    – B Seven
    Commented Oct 27, 2012 at 3:11
  • 2
    What I can see, you have two options, either use one function (like @Bernhard described above), and branch depending on directory (just like he said), or, you could put the parameters in the directories. Come to think of it, it doesn't have to be scripts, you could just put a file (touch .TESTNO; echo 2 > .TESTNO) in each directory, and then, in your function, look for that file, and branch according to what test number the .TESTNO file contains. Although not at all difficult, you probably cannot use an alias for this; you must use a function. Commented Oct 27, 2012 at 5:17
5

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

Here's a demo:

enter image description here

Funny enough, I actually used go as an example in the demo. I did not show switching directories (something I should change about the demo) but the functions with the la command are indeed local to the directory they are defined in.

1
  • … Thansk for posting the repo. I remember having used a while ago but couldn't find it since it's name has changed to funky.
    – gruentee
    Commented Apr 27, 2022 at 11:15
3

I was searching for a way to do this for quite a while, and today I came up with a solution that is a synthesis of some of the other answers, but with a secret ingredient that spikes the sauce; direnv.

The problem with having .aliases that is read every time, as proposed by @teknopaul, is as mentioned, that you accumulate definitions and they never unload. direnv solves this issue by loading and unloading environment variables on a per-directory basis. Still, this just handles environment variables, but we can use this together with functions!

So here is my alias for npm (which, of course, is not an alias, but a function):

function npm(){ if [[ -z "$NPMBIN" ]]; then $(which npm) $@; else $NPMBIN $@; fi; }

You can also rewrite the above to a true alias, by executing the logic in a sub-shell, but then you need to mind your escaped quotes!

alias npm='bash -c "if [[ -z \"$NPMBIN\" ]]; then $(which npm) $@; else \"$NPMBIN\" $@; fi;"'
1
function go() {
  if [ ! -e "./.cmd1" ]
    then command go -a $1
    else command go -b $1
  fi
}

Similar thing, but assuming "go" is a command you want different functionality from in a specific directory.

0

i realized this via direnv and a shell script what is called via an alias

~/folder_a/.envrc

export GO_TO_DIR="./subdir_a"

~/folder_b/.envrc

export GO_TO_DIR="~/another_dir"

my go_to.sh

#!/bin/sh
value="${GO_TO_DIR}"

if [ -z $value ]
then
  exit 0
fi

cd $value

don't forget to make this file executeable

chmod u+x /path/to/script/go_to.sh

now i've set an alias to this script in my ~/.bashrc and ~/.zshrc and it works

alias goto="sh /path/to/script/go_to.sh"

bonus:

  1. i can sat a global env to change to a standard destination until it is overwritten with the directory specific env

  2. if no env is defined, nothing will happen

__

a second way without a script is to change the alias directly test if the env exists

alias goto='sh -c "if [ ! -z ${GO_TO_DIR} ]; then cd ${GO_TO_DIR}; fi;"'
0

Building upon @teknopaul his answer, I added a little hack that ensures the previous aliases get tossed by replacing the current shell with a new bash instance using exec:

cd () {
  builtin cd "$@" && exec bash
}

if [ -f $PWD/.aliases ]; then
    . $PWD/.aliases
fi

Note that this will break chaining cd with consecutive command executions

You must log in to answer this question.

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