Date, arithmetic, and ternary operator in one line
Clash Royale CLAN TAG#URR8PPP
I have a simple code to ensure a script takes at least x seconds (500 here) on Ubuntu
t1=$(date +%s)
# script is here
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
sleep $t
The code works perfectly, but I believe my coding is not efficient, and these three lines
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
should be expressed in one single line. My question is how to improve the code.
bash shell-script arithmetic
add a comment |
I have a simple code to ensure a script takes at least x seconds (500 here) on Ubuntu
t1=$(date +%s)
# script is here
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
sleep $t
The code works perfectly, but I believe my coding is not efficient, and these three lines
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
should be expressed in one single line. My question is how to improve the code.
bash shell-script arithmetic
Is this a Linux platform, or some UNIX? (More specifically, do you have GNUdate
?)
– roaima
Feb 4 at 21:48
2
There is much to be said for not sacrificing readability for perceived efficiency. If you compress that all into an inscrutable one-liner running as a subshell expansion as a parameter forsleep
, how are you going to unravel that when someone calls you at 4 in the morning the day after a most raucous party to debug it when it goes sideways?
– DopeGhoti
Feb 4 at 21:53
1
You could lose thet
andt2
entirely, but make sure your phone is switched off at 4am.sleep $( printf "%dn" $(( 500 - ($(date +%s) - t1) )) | sed 's/^-.*/1/' )
– roaima
Feb 4 at 22:01
1
@roaima Sorry for being vague. I updated the question. I haven't got stuck anywhere. I just want to improve my code, as I believe it is not the efficient way.
– Googlebot
Feb 4 at 22:01
@DopeGhoti very good point indeed.
– Googlebot
Feb 4 at 22:02
add a comment |
I have a simple code to ensure a script takes at least x seconds (500 here) on Ubuntu
t1=$(date +%s)
# script is here
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
sleep $t
The code works perfectly, but I believe my coding is not efficient, and these three lines
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
should be expressed in one single line. My question is how to improve the code.
bash shell-script arithmetic
I have a simple code to ensure a script takes at least x seconds (500 here) on Ubuntu
t1=$(date +%s)
# script is here
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
sleep $t
The code works perfectly, but I believe my coding is not efficient, and these three lines
t2=$(date +%s)
let "t = 500 - $t2 + $t1"
(( t = t>0 ? t : 1 ))
should be expressed in one single line. My question is how to improve the code.
bash shell-script arithmetic
bash shell-script arithmetic
edited Feb 4 at 22:18
jimmij
31.9k874108
31.9k874108
asked Feb 4 at 21:42
GooglebotGooglebot
499623
499623
Is this a Linux platform, or some UNIX? (More specifically, do you have GNUdate
?)
– roaima
Feb 4 at 21:48
2
There is much to be said for not sacrificing readability for perceived efficiency. If you compress that all into an inscrutable one-liner running as a subshell expansion as a parameter forsleep
, how are you going to unravel that when someone calls you at 4 in the morning the day after a most raucous party to debug it when it goes sideways?
– DopeGhoti
Feb 4 at 21:53
1
You could lose thet
andt2
entirely, but make sure your phone is switched off at 4am.sleep $( printf "%dn" $(( 500 - ($(date +%s) - t1) )) | sed 's/^-.*/1/' )
– roaima
Feb 4 at 22:01
1
@roaima Sorry for being vague. I updated the question. I haven't got stuck anywhere. I just want to improve my code, as I believe it is not the efficient way.
– Googlebot
Feb 4 at 22:01
@DopeGhoti very good point indeed.
– Googlebot
Feb 4 at 22:02
add a comment |
Is this a Linux platform, or some UNIX? (More specifically, do you have GNUdate
?)
– roaima
Feb 4 at 21:48
2
There is much to be said for not sacrificing readability for perceived efficiency. If you compress that all into an inscrutable one-liner running as a subshell expansion as a parameter forsleep
, how are you going to unravel that when someone calls you at 4 in the morning the day after a most raucous party to debug it when it goes sideways?
– DopeGhoti
Feb 4 at 21:53
1
You could lose thet
andt2
entirely, but make sure your phone is switched off at 4am.sleep $( printf "%dn" $(( 500 - ($(date +%s) - t1) )) | sed 's/^-.*/1/' )
– roaima
Feb 4 at 22:01
1
@roaima Sorry for being vague. I updated the question. I haven't got stuck anywhere. I just want to improve my code, as I believe it is not the efficient way.
– Googlebot
Feb 4 at 22:01
@DopeGhoti very good point indeed.
– Googlebot
Feb 4 at 22:02
Is this a Linux platform, or some UNIX? (More specifically, do you have GNU
date
?)– roaima
Feb 4 at 21:48
Is this a Linux platform, or some UNIX? (More specifically, do you have GNU
date
?)– roaima
Feb 4 at 21:48
2
2
There is much to be said for not sacrificing readability for perceived efficiency. If you compress that all into an inscrutable one-liner running as a subshell expansion as a parameter for
sleep
, how are you going to unravel that when someone calls you at 4 in the morning the day after a most raucous party to debug it when it goes sideways?– DopeGhoti
Feb 4 at 21:53
There is much to be said for not sacrificing readability for perceived efficiency. If you compress that all into an inscrutable one-liner running as a subshell expansion as a parameter for
sleep
, how are you going to unravel that when someone calls you at 4 in the morning the day after a most raucous party to debug it when it goes sideways?– DopeGhoti
Feb 4 at 21:53
1
1
You could lose the
t
and t2
entirely, but make sure your phone is switched off at 4am. sleep $( printf "%dn" $(( 500 - ($(date +%s) - t1) )) | sed 's/^-.*/1/' )
– roaima
Feb 4 at 22:01
You could lose the
t
and t2
entirely, but make sure your phone is switched off at 4am. sleep $( printf "%dn" $(( 500 - ($(date +%s) - t1) )) | sed 's/^-.*/1/' )
– roaima
Feb 4 at 22:01
1
1
@roaima Sorry for being vague. I updated the question. I haven't got stuck anywhere. I just want to improve my code, as I believe it is not the efficient way.
– Googlebot
Feb 4 at 22:01
@roaima Sorry for being vague. I updated the question. I haven't got stuck anywhere. I just want to improve my code, as I believe it is not the efficient way.
– Googlebot
Feb 4 at 22:01
@DopeGhoti very good point indeed.
– Googlebot
Feb 4 at 22:02
@DopeGhoti very good point indeed.
– Googlebot
Feb 4 at 22:02
add a comment |
2 Answers
2
active
oldest
votes
Here is how I would do it using bash
special parameter SECONDS
:
#!/bin/bash
SECONDS=0
# script is here
sleep "$(( 500 > SECONDS ? 500 - SECONDS : 1 ))"
Normally SECONDS
returns time (in seconds) since the script has started, but one can assign any value to (re)set the timer.
1
ZeroingSECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.
– ilkkachu
Feb 4 at 22:25
add a comment |
What your script is, is non-portable (since you're using let
and (( .. ))
), confusing (since you're using both let
and (( .. ))
), lacking in documentation (there are no comments, and the variable names are non-descriptive), and marginally unsafe (since you haven't quoted the expansion of $t
).
If you want a rewrite, here's mine:
#!/bin/sh
min_duration=500
t_start=$(date +%s)
# script is here
t_end=$(date +%s)
elapsed=$(( t_end - t_start ))
# sleep long enough to make sure 'min_duration' seconds has elapsed,
# but at least 1 second
sleep "$(( elapsed < min_duration ? min_duration - elapsed : 1 ))"
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
Feb 4 at 22:11
1
@roaima The exit status when the calculation results in a zero. It matters when running underset -e
. Personally, I think I would have usedelapsed=$(( ... ))
. Also notice that he's writing for/bin/sh
, notbash
.
– Kusalananda
Feb 4 at 22:16
@roaima, I was just thinking about the portability point. At leastdash
andbusybox
don't support(( .. ))
. With Bash, I'd use(( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone usesset -e
, but let's not go there...)
– ilkkachu
Feb 4 at 22:18
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
Feb 4 at 22:19
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498680%2fdate-arithmetic-and-ternary-operator-in-one-line%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here is how I would do it using bash
special parameter SECONDS
:
#!/bin/bash
SECONDS=0
# script is here
sleep "$(( 500 > SECONDS ? 500 - SECONDS : 1 ))"
Normally SECONDS
returns time (in seconds) since the script has started, but one can assign any value to (re)set the timer.
1
ZeroingSECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.
– ilkkachu
Feb 4 at 22:25
add a comment |
Here is how I would do it using bash
special parameter SECONDS
:
#!/bin/bash
SECONDS=0
# script is here
sleep "$(( 500 > SECONDS ? 500 - SECONDS : 1 ))"
Normally SECONDS
returns time (in seconds) since the script has started, but one can assign any value to (re)set the timer.
1
ZeroingSECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.
– ilkkachu
Feb 4 at 22:25
add a comment |
Here is how I would do it using bash
special parameter SECONDS
:
#!/bin/bash
SECONDS=0
# script is here
sleep "$(( 500 > SECONDS ? 500 - SECONDS : 1 ))"
Normally SECONDS
returns time (in seconds) since the script has started, but one can assign any value to (re)set the timer.
Here is how I would do it using bash
special parameter SECONDS
:
#!/bin/bash
SECONDS=0
# script is here
sleep "$(( 500 > SECONDS ? 500 - SECONDS : 1 ))"
Normally SECONDS
returns time (in seconds) since the script has started, but one can assign any value to (re)set the timer.
edited Feb 4 at 22:21
Kusalananda
132k17253416
132k17253416
answered Feb 4 at 22:13
jimmijjimmij
31.9k874108
31.9k874108
1
ZeroingSECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.
– ilkkachu
Feb 4 at 22:25
add a comment |
1
ZeroingSECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.
– ilkkachu
Feb 4 at 22:25
1
1
Zeroing
SECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.– ilkkachu
Feb 4 at 22:25
Zeroing
SECONDS
doesn't hurt, and at least makes the initial value explicit, but since it tells the time since the script started you don't have to zero it. Unless the script does something else first, of course.– ilkkachu
Feb 4 at 22:25
add a comment |
What your script is, is non-portable (since you're using let
and (( .. ))
), confusing (since you're using both let
and (( .. ))
), lacking in documentation (there are no comments, and the variable names are non-descriptive), and marginally unsafe (since you haven't quoted the expansion of $t
).
If you want a rewrite, here's mine:
#!/bin/sh
min_duration=500
t_start=$(date +%s)
# script is here
t_end=$(date +%s)
elapsed=$(( t_end - t_start ))
# sleep long enough to make sure 'min_duration' seconds has elapsed,
# but at least 1 second
sleep "$(( elapsed < min_duration ? min_duration - elapsed : 1 ))"
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
Feb 4 at 22:11
1
@roaima The exit status when the calculation results in a zero. It matters when running underset -e
. Personally, I think I would have usedelapsed=$(( ... ))
. Also notice that he's writing for/bin/sh
, notbash
.
– Kusalananda
Feb 4 at 22:16
@roaima, I was just thinking about the portability point. At leastdash
andbusybox
don't support(( .. ))
. With Bash, I'd use(( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone usesset -e
, but let's not go there...)
– ilkkachu
Feb 4 at 22:18
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
Feb 4 at 22:19
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
add a comment |
What your script is, is non-portable (since you're using let
and (( .. ))
), confusing (since you're using both let
and (( .. ))
), lacking in documentation (there are no comments, and the variable names are non-descriptive), and marginally unsafe (since you haven't quoted the expansion of $t
).
If you want a rewrite, here's mine:
#!/bin/sh
min_duration=500
t_start=$(date +%s)
# script is here
t_end=$(date +%s)
elapsed=$(( t_end - t_start ))
# sleep long enough to make sure 'min_duration' seconds has elapsed,
# but at least 1 second
sleep "$(( elapsed < min_duration ? min_duration - elapsed : 1 ))"
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
Feb 4 at 22:11
1
@roaima The exit status when the calculation results in a zero. It matters when running underset -e
. Personally, I think I would have usedelapsed=$(( ... ))
. Also notice that he's writing for/bin/sh
, notbash
.
– Kusalananda
Feb 4 at 22:16
@roaima, I was just thinking about the portability point. At leastdash
andbusybox
don't support(( .. ))
. With Bash, I'd use(( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone usesset -e
, but let's not go there...)
– ilkkachu
Feb 4 at 22:18
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
Feb 4 at 22:19
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
add a comment |
What your script is, is non-portable (since you're using let
and (( .. ))
), confusing (since you're using both let
and (( .. ))
), lacking in documentation (there are no comments, and the variable names are non-descriptive), and marginally unsafe (since you haven't quoted the expansion of $t
).
If you want a rewrite, here's mine:
#!/bin/sh
min_duration=500
t_start=$(date +%s)
# script is here
t_end=$(date +%s)
elapsed=$(( t_end - t_start ))
# sleep long enough to make sure 'min_duration' seconds has elapsed,
# but at least 1 second
sleep "$(( elapsed < min_duration ? min_duration - elapsed : 1 ))"
What your script is, is non-portable (since you're using let
and (( .. ))
), confusing (since you're using both let
and (( .. ))
), lacking in documentation (there are no comments, and the variable names are non-descriptive), and marginally unsafe (since you haven't quoted the expansion of $t
).
If you want a rewrite, here's mine:
#!/bin/sh
min_duration=500
t_start=$(date +%s)
# script is here
t_end=$(date +%s)
elapsed=$(( t_end - t_start ))
# sleep long enough to make sure 'min_duration' seconds has elapsed,
# but at least 1 second
sleep "$(( elapsed < min_duration ? min_duration - elapsed : 1 ))"
edited Feb 4 at 22:19
answered Feb 4 at 22:09
ilkkachuilkkachu
59.9k997169
59.9k997169
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
Feb 4 at 22:11
1
@roaima The exit status when the calculation results in a zero. It matters when running underset -e
. Personally, I think I would have usedelapsed=$(( ... ))
. Also notice that he's writing for/bin/sh
, notbash
.
– Kusalananda
Feb 4 at 22:16
@roaima, I was just thinking about the portability point. At leastdash
andbusybox
don't support(( .. ))
. With Bash, I'd use(( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone usesset -e
, but let's not go there...)
– ilkkachu
Feb 4 at 22:18
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
Feb 4 at 22:19
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
add a comment |
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
Feb 4 at 22:11
1
@roaima The exit status when the calculation results in a zero. It matters when running underset -e
. Personally, I think I would have usedelapsed=$(( ... ))
. Also notice that he's writing for/bin/sh
, notbash
.
– Kusalananda
Feb 4 at 22:16
@roaima, I was just thinking about the portability point. At leastdash
andbusybox
don't support(( .. ))
. With Bash, I'd use(( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone usesset -e
, but let's not go there...)
– ilkkachu
Feb 4 at 22:18
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
Feb 4 at 22:19
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
1
1
Is there any practical difference between your
: "$(( elapsed = t_end - t_start ))"
and simply (( elapsed = t_end - t_start ))
?– roaima
Feb 4 at 22:11
Is there any practical difference between your
: "$(( elapsed = t_end - t_start ))"
and simply (( elapsed = t_end - t_start ))
?– roaima
Feb 4 at 22:11
1
1
@roaima The exit status when the calculation results in a zero. It matters when running under
set -e
. Personally, I think I would have used elapsed=$(( ... ))
. Also notice that he's writing for /bin/sh
, not bash
.– Kusalananda
Feb 4 at 22:16
@roaima The exit status when the calculation results in a zero. It matters when running under
set -e
. Personally, I think I would have used elapsed=$(( ... ))
. Also notice that he's writing for /bin/sh
, not bash
.– Kusalananda
Feb 4 at 22:16
@roaima, I was just thinking about the portability point. At least
dash
and busybox
don't support (( .. ))
. With Bash, I'd use (( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone uses set -e
, but let's not go there...)– ilkkachu
Feb 4 at 22:18
@roaima, I was just thinking about the portability point. At least
dash
and busybox
don't support (( .. ))
. With Bash, I'd use (( .. ))
since it looks less ugly to me. The exit status shouldn't matter (well, unless someone uses set -e
, but let's not go there...)– ilkkachu
Feb 4 at 22:18
@Kusalananda, argh, of course with
elapsed=$((..))
... Thanks.– ilkkachu
Feb 4 at 22:19
@Kusalananda, argh, of course with
elapsed=$((..))
... Thanks.– ilkkachu
Feb 4 at 22:19
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
@Kusalananda ah yes. Thankyou.
– roaima
Feb 5 at 0:18
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498680%2fdate-arithmetic-and-ternary-operator-in-one-line%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Is this a Linux platform, or some UNIX? (More specifically, do you have GNU
date
?)– roaima
Feb 4 at 21:48
2
There is much to be said for not sacrificing readability for perceived efficiency. If you compress that all into an inscrutable one-liner running as a subshell expansion as a parameter for
sleep
, how are you going to unravel that when someone calls you at 4 in the morning the day after a most raucous party to debug it when it goes sideways?– DopeGhoti
Feb 4 at 21:53
1
You could lose the
t
andt2
entirely, but make sure your phone is switched off at 4am.sleep $( printf "%dn" $(( 500 - ($(date +%s) - t1) )) | sed 's/^-.*/1/' )
– roaima
Feb 4 at 22:01
1
@roaima Sorry for being vague. I updated the question. I haven't got stuck anywhere. I just want to improve my code, as I believe it is not the efficient way.
– Googlebot
Feb 4 at 22:01
@DopeGhoti very good point indeed.
– Googlebot
Feb 4 at 22:02