Date, arithmetic, and ternary operator in one line
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
yesterday
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
yesterday
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
yesterday
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
yesterday
@DopeGhoti very good point indeed.
– Googlebot
yesterday
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 yesterday
jimmij
31.2k871106
31.2k871106
asked yesterday
GooglebotGooglebot
487621
487621
Is this a Linux platform, or some UNIX? (More specifically, do you have GNUdate
?)
– roaima
yesterday
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
yesterday
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
yesterday
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
yesterday
@DopeGhoti very good point indeed.
– Googlebot
yesterday
add a comment |
Is this a Linux platform, or some UNIX? (More specifically, do you have GNUdate
?)
– roaima
yesterday
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
yesterday
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
yesterday
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
yesterday
@DopeGhoti very good point indeed.
– Googlebot
yesterday
Is this a Linux platform, or some UNIX? (More specifically, do you have GNU
date
?)– roaima
yesterday
Is this a Linux platform, or some UNIX? (More specifically, do you have GNU
date
?)– roaima
yesterday
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
yesterday
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
yesterday
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
yesterday
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
yesterday
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
yesterday
@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
yesterday
@DopeGhoti very good point indeed.
– Googlebot
yesterday
@DopeGhoti very good point indeed.
– Googlebot
yesterday
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
yesterday
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
yesterday
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
yesterday
@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
yesterday
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
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
yesterday
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
yesterday
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 yesterday
Kusalananda
128k16241398
128k16241398
answered yesterday
jimmijjimmij
31.2k871106
31.2k871106
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
yesterday
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
yesterday
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
yesterday
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
yesterday
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
yesterday
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
yesterday
@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
yesterday
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
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
yesterday
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
yesterday
@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
yesterday
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
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 yesterday
answered yesterday
ilkkachuilkkachu
58.1k889164
58.1k889164
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
yesterday
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
yesterday
@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
yesterday
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
add a comment |
1
Is there any practical difference between your: "$(( elapsed = t_end - t_start ))"
and simply(( elapsed = t_end - t_start ))
?
– roaima
yesterday
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
yesterday
@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
yesterday
@Kusalananda, argh, of course withelapsed=$((..))
... Thanks.
– ilkkachu
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
1
1
Is there any practical difference between your
: "$(( elapsed = t_end - t_start ))"
and simply (( elapsed = t_end - t_start ))
?– roaima
yesterday
Is there any practical difference between your
: "$(( elapsed = t_end - t_start ))"
and simply (( elapsed = t_end - t_start ))
?– roaima
yesterday
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
yesterday
@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
yesterday
@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
yesterday
@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
yesterday
@Kusalananda, argh, of course with
elapsed=$((..))
... Thanks.– ilkkachu
yesterday
@Kusalananda, argh, of course with
elapsed=$((..))
... Thanks.– ilkkachu
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
@Kusalananda ah yes. Thankyou.
– roaima
yesterday
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
yesterday
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
yesterday
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
yesterday
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
yesterday
@DopeGhoti very good point indeed.
– Googlebot
yesterday