Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

With this release, bash now has three built-in variables (um, I mean "parameters") whose values are updated every time they're read:

$RANDOM yields a random integer in the range 0..32767. (This feature was already there.)

$EPOCHSECONDS yields the whole number of seconds since the epoch.

$EPOCHREALTIME yields the number of seconds since the epoch with microsecond precision.

I'm thinking of a new shell feature that would allow the user to define similar variables. For example, I have $today set to the current date in YYYY-MM-DD format, and I have to jump through some minor hoops to keep it up to date.

Does anyone else think this would be useful enough to propose as a new bash feature? Would it create any potential security holes? Should variables like $PATH be exempted?

(Of course this doesn't add any new functionality, since I could use "$(date +%F)" in place of "$today". It's just a bit of syntactic sugar.)



Please no. The parallel universe Me where I didn't happen to read this random thread would never know, consequently never expect random variables to do that. And curse you forever if I found out while banging my head debugging some buggy script.


Yeah what's wrong with functions? Clearly the Bash developers are continuing their tradition of obeying the principle of most surprise.


Judging from this thread, Bash doesn’t seem to be the only shell to support these types of variables, but I agree – it’s unintuitive and surprising.


How does function sound for a syntactic sugar?

  $ today() { date +%F; }
  $ echo Today, $(today) is a great day!
  Today, 2019-01-08 is a great day!


Not as good. I use $today a lot in file and directory names, The overhead of having to type $(today) rather than $today would be, for me, significant.

I do have a workaround for this particular case:

    PROMPT_COMMAND='today=$(printf "%(%F)T\n" -1)'
but it only works in bash 4.2 and later.

I could use

    PROMPT_COMMAND='today=$(date +%F)'
but I'm trying to avoid executing an external command on every prompt. (Maybe the overhead is low enough that it's not worth worrying about.)

My thoughts are (a) if user-defined special variables like this were a shell feature, I could find other uses for them and (b) it seems neater to make such a feature available to users rather than restricting it to three special-case built-in variables.

On the other hand, it might have been cleaner for $RANDOM, $EPOCHSECONDS, and $EPOCHREALTIME to be implemented as built-in functions rather than as special variables.


I have a better (at least cleaner IMHO) workaround:

    PROMPT_COMMAND='printf -v today "%(%F)T" -1'
printf's "-v" option was added in bash 4.0.

printf's "%(...)T" format was added in bash 4.2.

The "-1" argument became optional in bash 4.3.

So here's what I now have in my .bashrc :

    if [[ "$BASH_VERSION" > "4.2" ]] ; then
        PROMPT_COMMAND='printf -v today "%(%F)T" -1'
    else
        PROMPT_COMMAND='today=$(date +%F)'
    fi
(The "> 4.2" test is true for bash 4.2 and later, since the value of $BASH_VERSION for 4.2 is "4.2.0(1)-release". The ">" does a string comparison. I'll have to revisit this when and if there's a bash version 10.0, probably using $BASH_VERSINFO.)


It's not as nice, "cat $today" is easier to type than "cat $(today)" and would give better completion, just declared matching variables instead of matching functions, files and executables.

On the plus side, TIL the subshell syntax plays well with eval/expand shortcut (ctrl+alt+e).


Wouldn't "cat $today" result with "cat: No such file or directory: 2019-01-08"? Did you mean echo instead of cat?


My real life use case for these dynamic variables would be more like "cat/vim/cp $log" to get today's log file which would expand to something like /somedir/logs/201901/09/product.log. Handy when you have a large matrix of products/environments.


Only in the case when no such file exists in the current directory :)


* "cat $today" is easier to type than "cat $(today)"*

Except you should really be in the habit of typing "cat ${today}" ;)


Except you should really be in the habit of typing `cat "${today}"` ;) Quote everything!


Why? The {} doesn't prevent glob expansion or field separation.


It's not obvious that just expanding a variable runs code though.


You mean like Ksh's discipline functions?

  dualbus@system76-pc:~$ ksh -c 'date=; date.get() { .sh.value=$(date +%s); }; echo $date; sleep 5; echo $date'
  1546926637
  1546926642
See: https://docs.oracle.com/cd/E36784_01/html/E36870/ksh-1.html ("Discipline Functions")


Yes, just like that!


Syntactic sugar is a phrase permanently marred for me by the ruby community: it means "cognitive load for other people who know the language but don't keep up with the faddy bits". It made me tremendously sad.


Yeah, but C-style "for" loops are nice, right ? Still, they really are a syntactic sugar for a "while".

The problem is more with a language having fady bits and people using them when they don't make the code clearer, than with syntactic sugar.


C-style "for" loops are nice, right

Well... I know macros are supposed to be bad, but.. I've been programming in C for a long time, but only recently tried 'sugaring' my loops with

  #define _(x,y) for (x=0;x<(y);x++)
..which has worked soo well, I'm sticking with it. It makes programming in C much more pleasurable. (My programs mostly have a lot of nested loops over multidimensional arrays, mostly from 0, inc'ed by 1)

So now instead of e.g.

  for (i=0;i<WID;i++) 
    for (j=0;j<HEI;j++) {
it's just

  _(i,WID) _(j,HEI) {
which makes me smile every time.


Sure, I agree actually - if you are going to have a language that has lots of nice syntax, _let it be built in from the start_. Or only released at major increments, etc etc.


Hopefully Bash 6.0 then


Nicely put.

I'm reminded of the Jargon file that says "Syntactic sugar causes cancer of the semicolon."


$RANDOM is new in bash 5.0? i'm curious. This has been documented for ages, afaik. headtilt


No $RANDOM has been there since 80s. BASH_ARGV0, EPOCHSECONDS, and EPOCHREALTIME are new.


No, it's old; I've updated my comment accordingly.


word wasn't hating, just ... curious. the others do seem new. :)


What is the advantage of this technique over a shell built-in or function that echoes that value?


You can already do this interactively with PROMPT_COMMAND, e.g.

  PROMPT_COMMAND='date=$(date +%D);time=$(date +%T)'


Not quite - that is run before your prompt is displayed.

  $ PROMPT_COMMAND='time=$(date +%T)'
  $ echo $time;date +%T
  12:19:07
  12:20:19
Thus it will show the time after your last command returned rather than the current time.


Anyone knows why a `microsecond since epoch` is named "realtime"? What is so "guaranteed" about it?


bash's EPOCHREALTIME was inspired by mksh, which was in turn inspired by zsh. And in zsh, EPOCHREALTIME was named after the system real-time clock (specifically the CLOCK_REALTIME clock ID passed to clock_gettime()). And i imagine that was named by analogy with hardware real-time clocks, since they both track human ('real') time. But i don't know much about electronics or the history of POSIX clock sources.


And does it even count leap seconds? Regular Unix timestamps do not (time stands still during leap seconds)


Here is my favourite bash script: https://blog.ashfame.com/2018/02/deploying-lambdas-multiple-...

Deploy a lambda function in multiple regions (15 regions!) with just one bash script using Apex up.

Add route53 on top with Latency Based Routing enabled and you've a latency in 10s of millsecond from anywhere on the globe without paying a hefty fee for this kind of latency.


How is that in any way related to the parent comment?


It's not my blog, i thought mentioning a script in bash would be a good idea.


Love Apex Up




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: