4

I would like to create an alias in my ~/.bash_profile that will:

  1. Take two arguments $1 $2
  2. Pass these to diff
  3. Pipe the output to less

I have not found any solutions on Stack that do what I need, but please point me to any you know of! The following lines appear in my ~/.bash_profile:

alias reload='. ~/.bash_profile'
alias aliases='emacs ~/.bash_profile; reload'
function dif () { diff "$1" "$2" | less; }
alias different='dif' 

When I try:

gsuehr$ reload
-bash: /Users/gregorysuehr/.bash_profile: line 93: syntax error: unexpected end of file 

I am certain that I am not understanding how to use a bash function. I've confirmed that the 2 aliases: reload aliases work as expected if I comment out the function declaration. Could anybody share knowledge about:

  1. Why EOF error is occurring?
  2. How to use functions within bash to accomplish what I am trying here?
3
  • 2
    Cut and paste your current ~/.bash_profile into shellcheck.net and fix the errors that shellcheck finds. If the meaning of the error messages is not obvious, ask here.
    – John1024
    Commented Jul 8, 2016 at 6:20
  • 3
    The error you get is not in the code you pasted. Commented Jul 8, 2016 at 6:22
  • 1
    The function and the aliases doesn't seem to be the cause of the problem. Have a look at your .bash_profile file instead. Look for unterminated strings, if-statements or loops.
    – Kusalananda
    Commented Jul 8, 2016 at 6:27

2 Answers 2

9

You can't use an alias to add stuff after arguments, you need a function. Use an alias only to give an alternate name to a command (alias myalias=mycommand) or to supply initial arguments (alias myalias='foo --option1 --option2').

In bash, you can use any of function myfunction { … } or myfunction () { … } or function myfunction () { … } to define a function. The form myfunction () … has the advantage of being portable to all sh shells. The forms with the function keyword have the advantage of working even if myfunction is an alias (you can use \myfunction () … to make the standard form work in that case). Apart from the alias thing, these syntaxes are exactly equivalent in bash.

What follows the function name or the () must be a well-formed complex command. Judging by your answer (the code in your question does not produce the error message, obviously you didn't post the version you tested), your mistake was that the complex command you wrote is not correct. The braces { and } are only recognized as begin-list and end-list syntax when they are the first thing in a command, so you need a line break or a semicolon before the closing brace.

Additionally, instead of passing two arguments to diff and ignoring the others, you should pass them all. That's what "$@" is for.

function dif () { diff "$1" "$2" | less; }

Furthermore, customizations for interactive bash sessions should go into .bashrc, not .bash_profile. .bash_profile is only read by login shells, it isn't read when you open a new instance of bash, e.g. in a terminal. Because of a design defect in bash, .bashrc is not read by login shells even if they're interactive, so you should put this line in your .bash_profile:

if [[ $- == *i* ]]; then . ~/.bashrc; fi

and put interactive customization such as aliases, functions like dif, key bindings, prompts, etc. in ~/.bashrc.

1

Posting this as an answer rather than updating my question, please let me know if I should do otherwise!

In this case, my .bash_profile failed to reload because I misunderstood bash function syntax.

    function dif () { diff $1 $2 | less }

Should just be:

    dif () { diff $1 $2 | less; }

edit: Added semicolon after less. I have verified that it works!

Thanks to @John1024 for the link to shellcheck.net, that's a great resource!

4
  • 1
    I suspect that you meant to write dif () { diff $1 $2 | less; } where the inner command is diff and the final command is terminated with a semicolon.
    – John1024
    Commented Jul 8, 2016 at 18:17
  • 1
    dif () { dif $1 $2 | less } most definitely does not work in bash. Commented Jul 9, 2016 at 0:05
  • @John1024 yes, I did forget the semicolon. Added in an edit, sorry guys!
    – g_sue
    Commented Jul 9, 2016 at 22:51
  • Worked great for me: i just used it for killing process based on names (that wouldn't work with killall): killit () { ps aux | grep $1 | grep -v grep | awk '{print $2}' | xargs sudo kill -9; } Commented Mar 22, 2022 at 13:24

You must log in to answer this question.

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