"syntax error near unexpected token" after editing .bashrc

mook765 is entirely correct about the cause of the problem, and the solution proposed in that answer fixes the syntax error, but I recommend you solve it in a different way.

It's fine to put alias definitions in .bashrc, but it is best not to put them--or anything--at the very top of that file.

We tend to think of .bashrc as being sourced only by interactive shells, but this is actually not the case. Non-interactive remote shells (if bash identifies them as such) also source .bashrc. That is why Ubuntu's default .bashrc1 contains this code:2

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Basically everything you put in .bashrc, including but not limited to alias definitions, should go somewhere below that. You should only ever put your own code above that code if you have a clear reason to do so, which is rare.

You can put your alias definitions anywhere below that code, though I suggest putting them at the very end of the file. Or you might prefer to put them near some of the existing alias definitions in the file. Or you might prefer to put them in the separate file ~/.bash_aliases, which you can create if it does not exist.3 Any of these choices is fine.

Here's one of the more common examples of the bizarre and unexpected effects putting one's own code above the interactivity check can have. That particular problem occurs when the code produces output, which should not happen from an alias definition. (The alias, when used, may of course expand to a command that produces output, but a syntactically correct alias definition should not produce output unless the -p option is passed to alias.) I don't expect alias definitions to usually cause problems even if they run in non-interactive shells. Non-interactive shells don't perform alias expansion by default anyway (though this is merely a default). However, if they do end up producing unexpected effects, it's likely no one will think to check that.

This is admittedly only a weak reason to avoid putting alias definitions above the interactivity check in .bashrc. However, since there is absolutely no benefit of doing so compared to putting them anywhere else in the file, I recommend following the general approach of only putting code above that check that you deliberately intend to run in non-interactive remote shells.


The other interesting aspect of this is why this was a syntax error:

alias pbpaste='xclip -selection clipboard -o'# ~/.bashrc: executed by bash(1) for non-login shells.

# starts comments, which are permitted to follow commands. However, the # character does not have the effect of starting a comment when it appears in a larger word, except as the first character of that word. (In this sense, "word" includes things like pbpaste='xclip -selection clipboard -o'#, due to quoting.) The following text, which was intended as a comment, is taken as additional arguments to the alias builtin. But an error occurs while parsing them, due to the unexpected presence of (, which has special meaning to the shell, but which does not make sense in that context. The effect is that the alias builtin actually never runs, and you get a syntax error instead.

Therefore, it would actually be possible to fix the syntax error with a one-character edit, by putting a space between the ' and # characters on that line. But as detailed above, I recommend going further and moving the alias definitions much lower in the file.


1The default .bashrc in Ubuntu can be viewed at /etc/skel/.bashrc, so long as you have not modified that file. This is copied into a user's home directory when the user is created. Like many files in Ubuntu, this file is minimally changed from Debian, the distribution from which Ubuntu is derived. The advice in this post applies to Bash in Debian as well as Ubuntu, but it does not necessarily apply without modification to Bash in all GNU/Linux systems.

2It is also possible, though rare, to start bash as a non-interactive login shell. Like interactive login shells, such a shell sources ~/.profile automatically, and the default ~./profile in Ubuntu explicitly sources ~/.bashrc. Besides preventing unintentional execution in non-interactive remote shells, putting your additions to ~/.bashrc below the interactivity check also prevents it from being unintentionally executed in the strange case of a non-interactive login shell.

3Ubuntu's default .bashrc checks if ~/.bash_aliases exists ([ -f ~/.bash_aliases ]) and sources it (. ~/.bash_aliases) if it does. The code you posted verifies that your modified .bashrc file does perform those actions--it looks like the only change to it was the code you added at the top.


The caveat is in the second line:

alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'# ~/.bashrc: executed by bash(1) for non-login shells.

That should be:

alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'
# ~/.bashrc: executed by bash(1) for non-login shells.

It looks like you forgot to hit Enter after entering the second alias which resulted in # ~/.bash... directly following your alias definition in the same line. Without a preceding space # ~/.bash... could not be interpreted as a comment by the shell but as a part of the argument of the alias command.

I'd also recommend to place aliases in the file ~/.bash_aliases which will be sourced when ~/.bashrc is executed, so you don't need to edit ~/.bashrc and eventually mess it up.

If you insist on placing aliases in ~/.bashrc, add them at the end of the file.

For deeper insight into this topic, please refer to Eliah's excellent answer to your question.