1

Hel‌lo! Before I begin, my question is not a duplicate of this: https://askubuntu.com/questions/1071263/multi-line-alias-in-bash or this: Multiple commands in an alias for bash. And I've read the answers thoroughly.

My issue is that when I assign a variable inside a multi-line alias, something goes wrong in which it causes the shell to wait for another argument.

Here's a working alias:

$ alias alias1='var1="$(date)" ; echo $var1'
Wed Jul 28 18:07:37 +0230 2021

But if I write it in multiple lines, shell waits for another argument:

$ alias alias1='var1="$(date)"
> echo $var1'
$ alias1
$ hello
Wed Jul 28 18:10:28 +0230 2021 hello

I know the issue is with date but I don't understand what is happening.

I tried putting ; at the end of the first line, and it didn't fix the issue, but I put && and it fixed the issue, \ also fixed the issue which is weird to me because \ is for line continuation:

$ alias alias1='var1="$(date)" \ 
echo $var1'
$ alias1
Wed Jul 28 18:12:47 +0230 2021

Thanks in advance.

Shayan
  • 709
  • 1
  • 15
  • 31
  • I'm not sure what is going on, but you can fix it by using a function instead of an alias. – Socowi Jul 28 '21 at 15:51
  • Why do you think the backslash result is weird? It makes it ignore the newline, so it's like a single command `var1="$(date)" echo $var1` – Barmar Jul 28 '21 at 15:55
  • @Socowi But as I've said, I read all the answers on the links I put, they also said that functions are better, but I'm asking this question for learning purposes! – Shayan Jul 28 '21 at 16:22
  • @Barmar Because they are separate commands, thus they should not be on the same line and should be on different lines! – Shayan Jul 28 '21 at 16:22
  • Yes, but you're also allowed to put variable assignments at the beginning of any command. Try it as an ordinary command line. – Barmar Jul 28 '21 at 16:23
  • Aliases are executed in a weird way because of the way they substitute into the command line. – Barmar Jul 28 '21 at 16:25
  • Ah, I see, Thanks very much. If you could please write an answer, I would highly appreciate it. – Shayan Jul 28 '21 at 16:27
  • It would be a better choice to make this a function instead of an alias in the first place. `alias1() { var=$(date); echo "$var1"; }` -- still works if you change the `;`s to newlines, too. – Charles Duffy Jul 28 '21 at 17:21
  • Can't reproduce on Bash 5.1.8. – oguz ismail Jul 28 '21 at 17:22
  • @oguzismail yes exactly, I get different results on different systems. Read vdavid's answer please. – Shayan Jul 28 '21 at 17:30

1 Answers1

2

The one thing that never failed me so far is curly braces.

alias alias1='{ var1="$(date)"
echo $var1; }'

Make sure to add a space character after the opening curly brace and before the closing one. If there is a command one the same line of the closing brace, make sure to add a ; as shown above.

You can use newlines to get rid of that ugly ; if you wish to do so:

alias alias1='{
var1="$(date)"
echo $var1
}'

You can do the same with parentheses () and actually the syntax is more forgiving, e.g. you don’t need the extra space characters nor the final semi-colon, but you don’t have access to variables that you have assigned inside your alias.

alias alias1='(var1="$(date)"
echo $var1)'

TL;DR: use curly braces if you want to have access to the variables after the alias is called, otherwise use parentheses to prevent your variables from leaking

Side note

I haven’t been able to find a source for explaining why it behaves like that, but multi-line aliases may respond differently from one system to another. In your case it seems to wait for user input. I have a CentOS distribution which works but also displays the prompt string:

[user@localhost tmp]$ alias alias1='var1="$(date)"
> echo $var1'
[user@localhost tmp]$ alias1
Wed Jul 28 18:09:32 CEST 2021 date printf \033]0;%s@%s:%s\007 user localhost /tmp

On my Cygwin embedded in MobaXterm, it simply displays nothing.

Bottom line: use multi-line aliases at your own risk.

vdavid
  • 2,434
  • 1
  • 14
  • 15