问题
You can think of this like a really simple stopwatch. I'm trying to hack together a bash script that displays the elapsed time since a specified date and updates the output every second.
First, Inside the script you'd specify a UNIX date: Fri Apr 14 14:00:00 EDT 2011
. This would be when the stopwatch starts.
Now, when you run the script, you'd see...
06d:10h:37m:01s
and a few seconds later you'd see...
06d:10h:37m:05s
I'm not trying to have a new line printed for every second that elapses. The script should only have 1 line of output, and update it every second. Obviously you could quit the script and start it up again at any time, and it would still be right on since the starting time is hard coded.
Any ideas?
回答1:
I use the following code snippet in long-running scripts. The timer runs in a function (separate process) which will be killed (trap) if the main process is terminated by a keybord interrupt. The output shows the time elapsed from the start of the timer:
... working [hh:mm:ss] 00:07:58
The snippet:
#=== FUNCTION ================================================================
# NAME: progressIndicatorTime
# DESCRIPTION: Display a progress indicator with seconds passed.
# PARAMETERS: [increment] between 1 and 60 [sec], default is 2 [sec]
#===============================================================================
function progressIndicatorTime ()
{
declare default=2 # default increment [sec]
declare increment="${1:-$default}" # 1. parameter or default
declare format='\b\b\b\b\b\b\b\b%02d:%02d:%02d' # time format hh:mm:ss
declare timepassed=0
declare seconds minutes hours
[[ ! "$increment" =~ ^([1-9]|[1-5][0-9]|60)$ ]] && increment=$default
printf " ... working [hh:mm:ss] 00:00:00"
while : ; do # infinite loop
((seconds=timepassed%60))
((minutes=timepassed/60))
((hours=minutes/60))
((minutes=minutes%60))
printf "$format" $hours $minutes $seconds
sleep $increment || break # sleep ...
((timepassed+=increment))
done
} # ---------- end of function progressIndicatorTime ----------
progressIndicatorTime & # run progress indicator
declare progressIndicatorPid=${!} # save process ID
trap "kill $progressIndicatorPid" INT TERM # trap keyboard interrupt
#
# run long command
#
kill -s SIGTERM $progressIndicatorPid # terminate progress indicator
回答2:
The art could use some work, but give this a try:
#!/bin/bash
ref_date='Thu Apr 19 17:07:39 CDT 2012'
ref_sec=$(date -j -f '%a %b %d %T %Z %Y' "${ref_date}" +%s)
update_inc=1
tput clear
cat <<'EOF'
[|] [|]
_-'''''''''''''-_
/ \
| |
| |
| |
\ /
'-_____________-'
EOF
while :
do
((sec=$(date +%s) - ${ref_sec}))
((day=sec/86400))
((sec-=day*86400))
((hour=sec/3600))
((sec-=hour*3600))
((min=sec/60))
((sec-=min*60))
tput cup 6 14
printf "%.2id:%.2ih:%.2im:%.2is\r" ${day} ${hour} ${min} ${sec}
sleep ${update_inc}
done
exit 0
Note that the syntax of the first date command is for OSX.
For GNU date, use date --date="${ref_date}" +%s
回答3:
If you have Bash4 or ksh93, you can use the printf %()T
syntax to print strftime
formats. The following example is Bash 4 printing in the format you want. Bash precision is limited to 1 second. ksh93 supports floats and would require some modification.
#!/usr/bin/env bash
# To supply a default date/time. To use now as the default, leave empty, or run with a null first arg.
deftime='Fri Apr 14 14:00:00 EDT 2011'
if (( ${BASH_VERSINFO[0]}${BASH_VERSINFO[1]} >= 42 )); then
unixTime() {
printf ${2+-v "$2"} '%(%s)T' -1
}
else
unixTime() {
printf ${2+-v "$2"} "$(date '+%s')"
}
fi
stopWatch() {
local timestamp="$(date ${1:+'-d' "$1"} '+%s')" curtime day=$((60*60*24)) hour=$((60**2))
# unixTime -1 timestamp
while
unixTime -1 curtime
(( curtime -= timestamp ))
printf '%02dd:%02dh:%02dm:%02ds\r' $(( curtime / day )) $(( (curtime / hour) % 24 )) $(( (curtime / 60) % 60 )) $(( curtime % 60 ))
do sleep 1
done
}
stopWatch "${1-deftime}"
You may also be interested in the $SECONDS
variable. Unfortunately there is no convienient way to accept a human-readable date like you want. It would require considerable parsing effort. The date command (particularly GNU date) can do that to a limited extent.
来源:https://stackoverflow.com/questions/10229644/how-do-i-create-a-stopwatch-bash-script-to-constantly-display-elapsed-time