2

I made an alias alias goto="cd $@ && source ~/.zshrc" and it works, but only if I execute it twice. Even after I execute it twice in one shell, and if I want to move to another dir, I must again execute it twice. Why is that and how can I change that?

I need to type two times goto <dir>. The first time, I am still in the normal dir and the second time, I got to my destination. I need to source .zshrc, because I have a check for the path:

CURRENT=$PWD
AT_HOME=0
AT_ROOT=0

if [ $PWD = $HOME ]; then
    AT_HOME=1
elif [ $PWD = / ]; then
    AT_ROOT=1
else
    cd ../

    if [ $PWD = $HOME ]; then
        AT_HOME=1
    elif [ $PWD = / ]; then
        AT_ROOT=1
    else
        cd ../

        if [ $PWD = $HOME ]; then
            AT_HOME=1
        elif [ $PWD = / ]; then
            AT_ROOT=1
        fi
    fi
fi

cd $CURRENT

if [ $AT_HOME = 0 ]; then
    if [ $AT_ROOT = 0 ]; then
        ZSH_THEME="prompt-basename"
    else
        ZSH_THEME="prompt-normal"
    fi
else
    ZSH_THEME="prompt-normal"
fi

And it gives me full path (even at /usr/lib/jvm/java-13/bin) and when I source ~/.zshrc, it gives me the path I want (.../java-13/bin). By the way, replacing && with ; does not work neither.

Thanks!

*This is my first Question at stackxchange.com, so please don't be too rough.

4
  • What is in ~/.zshrc? Something in there might be tripping up zsh's alias system? Maybe if you edit your question to state what you are trying to do with the alias, someone who knows a cleaner and efficient way to do so will contribute an answer?
    – C. M.
    Commented May 14, 2021 at 1:12
  • 1
    It would be interesting to know the definition of "it works". What is the outcome when it does not work? Also, what do you have to enter twice - goto or the alias command? While I can assume the most likely answers to these questions, it's better that you clarify them. Commented May 14, 2021 at 1:25
  • 6
    Aliases don't use arguments, the $@ isn't what you think it is there.
    – muru
    Commented May 14, 2021 at 1:53
  • Does it work when you use ; instead of &&? If so, then cd's exit status is not 0, which means it failed.
    – glibg10b
    Commented May 14, 2021 at 5:47

2 Answers 2

4

First of all, aliases are not functions and do not accept arguments. Rather, aliases are simple substitutions: When you type goto foo on the command line and press Enter, the shell simply replaces goto with the value of the alias, before executing the command line.

Therefore, $@ does not expand to the arguments passed to your alias. In fact, in this case, it expands to the arguments passed to shell or the script you're sourcing. This is why goto works correctly the second time: You have now passed a directory as an argument when sourcing your .zshrc file and $@ will expand to that argument when you declare the alias again.

Additionally, since you're using "double quotes", $@ expands immediately when you declare the alias. To see that this is the case, right after your shell has started up, type alias without arguments to view your aliases.

If you want goto to be able to handle arguments, you should declare it as a function: goto() { cd $@ && ... }

However, as a rule, ⚠️you should not source ~/.zshrc. Depending on what's in your dotfiles, this can lead to all sorts of problems.

Instead, if you've made changes to your .zshrc file and you want to apply them, you should either restart your terminal (by closing the current tab/window and opening a new one) or restart the shell (by typing exec $SHELL).

8
  • The quotes will explain why OP has to "run it twice for it to work". The first time, the directory is an argument to ~/.zshrc as it gets sourced, so when the alias gets redefined during that, the $@ in the alias expands to the directory. So the second time the alias does have cd <whatever-path>, and it works.
    – muru
    Commented May 14, 2021 at 7:51
  • Thanks. I've updated my answer. Commented May 14, 2021 at 8:08
  • Why should you not source ~/.zshrc? Opening a new terminal will source it anyway, so why would there be an issue if you source it manually?
    – terdon
    Commented May 14, 2021 at 9:32
  • @terdon Because it's been sourced already when your shell started up and the order in which commands are run can matter. As a simple example, put ls() { command ls "$@" | less }; alias ls='ls -AF' into your .zshrc file, restart your shell, then source ~/.zshrc. Now you get an error zsh: defining function based on alias 'ls'. And that's only a fairly innocuous example. Things can get much more hairy than that, especially when your .zshrc in turn sources 3rd-party files. Commented May 14, 2021 at 9:39
  • That doesn't actually give me an error in zsh. But even if you can find some edge case that does, I am surprised you seem so adamant against this. I have been changing my ~/.bashrc and then sourcing it for many years and have never once encountered a problem. Maybe I have been lucky, but it seems more likely that what you are describing isn't a very common problem. Or perhaps it is special to zsh? Come teach me here: Is there any reason to avoid sourcing the shell's configuration file?
    – terdon
    Commented May 14, 2021 at 9:55
0

Marlon's answer works. Instead of making an alias, I did following function:

function goto {
    cd $@ && exec $SHELL
}

And it works perfectly. I also remarked, that sourcing ~/.zshrc takes longer and longer after every call of goto.

You must log in to answer this question.

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