I am trying to combine multiple commands into a single output.
#!/bin/bash
x=$(date +%Y)
x=$($x date +m%)
echo "$x"
This returns
./test.sh: line 4: 2011: command not found
x=$(echo $(date +%Y) $(date +%m))
(Note that you've transposed the characters % and m in the month format.)
In the second line, you're trying to execute $x date +m%. At this point, $x will be set to the year, 2011. So now it's trying to run this command:
2011 date +%m
Which is not what you want.
You could either do this:
x=$(date +%Y)
y=$(date +%m)
echo "$x $y"
Or that:
x=$(date +%Y)
x="$x $(date +%m)"
echo "$x"
Or simply use the final date format straight away:
x=$(date "+%Y %m")
echo $x
Maybe this?
#!/bin/bash
x=$(date +%Y)
x="$x$(date +%m)"
echo "$x"
...also correcting what appears to be a transpose in the format string you passed to date the second time around.
Semicolon to separate commands on the command line.
date +%Y ; date +m%
Or if you only want to run the second command if the first one succeeds, use double ampersand:
date +%Y && date +%m
Or if you want to run both commands simultaneously, mixing their output unpredictably (probably not what you want, but I thought I'd be thorough), use a single ampersand:
date +%Y & date +%m
echo ´date +%Y´ ´date +m%´
Note the reverse accent (´)
echo `date +%Y` `date +%m`
And to make the minimum change to the OP:
x=$(date +%Y)
x="$x $(date +%m)"
echo "$x"
Related
There are two functions : start и stop
they write the date and time to the file wrk.txt
This is what the contents of the file looks like after executing these commands:
START 10-08-2022 08:00:00
STOP 10-08-2022 08:06:33
function code:
#!/bin/bash
function start { echo 'START' $(date '+%d-%m-%Y %H:%M:%S') >> ~/Documents/wrk.txt
echo 'work started at:' $(date '+%d-%m-%Y %H:%M:%S') }
function stop { echo 'STOP' $(date '+%d-%m-%Y %H:%M:%S') >> ~/Documents/wrk.txt
echo 'work finished at:' $(date '+%d-%m-%Y %H:%M:%S')
}`
Question: how to take the last two lines from the file, remove the word START or STOP and calculate the time difference and save the result to a file
file data before calculations:
START 10-08-2022 08:00:00
STOP 10-08-2022 08:06:33
expected file data after calculations:
START 10-08-2022 08:00:00
STOP 10-08-2022 08:06:33
totalworktime: 00:06:33
The following may work for you:
#!/bin/bash
output_file="${1:-time_delta.out}"
df="%m-%d-%Y %H:%M:%S"
start=$(awk '{this=last; last=$0} END{print this}' wrk.txt)
sdate="${start/START /}"
end=$(awk '{this=last; last=$0} END{print last}' wrk.txt)
edate="${end/END /}"
printf "%s\n%s\n" "$start" "$end" >> "${output_file}"
echo $(( $(date -j -f "$df" "${edate}" +%s) \
- $(date -j -f "$df" "${sdate}" +%s) )) \
| awk '{printf("totalworktime: %02d:%02d:%02d\n", ($1/60/60),($1/60%60),($1%60))}' >> "${output_file}"
1) Set variable containing desired output file path/name either from first parameter passed to script or will default to ./time_delta.out. Set the date format expected from the wrk.txt contents.
output_file="${1:-time_delta.out}"
df="%m-%d-%Y %H:%M:%S"
2) Parse the second to the last line and the last line from wrk.txt and store the raw lines in variables start and end. Remove the leading START and END text from each variable using bash string replacement and store the results in sdate and edate variables.
start=$(awk '{this=last; last=$0} END{print this}' wrk.txt)
sdate="${start/START /}"
end=$(awk '{this=last; last=$0} END{print last}' wrk.txt)
edate="${end/END /}"
3) Add the raw $start AND $end variable contents to the $output_file
printf "%s\n%s\n" "$start" "$end" >> "${output_file}"
4) Convert the $sdate and $edate values to seconds from the epoch via date -j -f "$df" "${sdate}" +%s and date -j -f "$df" "${edate}" +%s. Subtract those values to get the delta and pass the result to awk for formatting as HH:MM:SS and append to ${output_file}
echo $(( $(date -j -f "$df" "${edate}" +%s) \
- $(date -j -f "$df" "${sdate}" +%s) )) \
| awk '{printf("totalworktime: %02d:%02d:%02d\n", ($1/60/60),($1/60%60),($1%60))}' >> "${output_file}"
Note, you might also consider replacing your start and stop functions with a single parameterized
function. At a minimum, store the date in a variable to avoid duplicate calls to date. Something
like the following:
add_time_log() {
local label="${1:-START}"
local msg="${2:-work started at}"
local log_file="${3:-time_log.txt}"
local now=$(date +"%m-%d-%Y %H:%M:%S")
printf "${msg}: ${now}\n"
printf "${label} ${now}\n" >> "${log_file}"
}
You can call the function as follows:
The folowing 2 are equivalent due to default parameter values
add_time_log
add_time_log START "work started at"
Adding END log
add_time_log END "work finished at"
Specifying all 3 parameters
add_time_log START "work started at" out.txt
add_time_log END "work finished at" out.txt
I have nested for loops going through dates and create a date. How can I check if that specific date is on the weekend or not?
String date is in the format of mm/dd/yyyy but can easily be changed. Each has its own variable $m $d $y
if [[ $(date +%u) -gt 5 ]] ; then
#do something
fi
above code works with current date, not sure how to translate that to accepting a string date.
You could use Ruby Date#cwday in your bash script. For example:
#!/bin/bash
y=2019
m=11
d=10
ruby -rtime -e "puts ([6,7].include? Date.new($y,$m,$d).cwday)"
which outputs true
I like more to use the variable directly:
if [[ $(date -d $your_variable +%u) -gt 5 ]]; then
#do something
fi
Just makes the code cleaner in my opinion.
I am trying to manipulate timestamps using date in shell script. My code is this
echo $(date -d '+10 mins' +%s%N)
This will print time 10 mins from current time in nanoseconds
1554242194228787268
When i move the echo statement inside a for loop to do a custom action based on the loop variable.
for repi in `seq 1 2`;
do
lp_incr=$((repi*10))
n_incr='+'$lp_incr' mins'
echo $(date -d $n_incr +%s%N)
done
Getting error like this
date: extra operand '+%s%N'
Remove that extra operand won't help me to view date alone
for repi in `seq 1 2`;
do
lp_incr=$((repi*10))
n_incr='+'$lp_incr' mins'
echo $n_incr
echo $(date -d $n_incr)
done
Again getting different error
+10 mins
date: the argument 'mins' lacks a leading '+';
$n_incr have the '+'still it throws an error.
It seems like i miss something in this. Entire motive is generate timestamp in nano seconds for some interval.
Thanks in advance for all suggestions or alternate approaches.
In
echo $(date -d $n_incr +%s%N)
$n_incr is expanded to
echo $(date -d +10 mins +%s%N)
Note that +10 mins is not a single argument, but two.
The fix is to quote the argument:
echo $(date -d "$n_incr" +%s%N)
You can also omit $n_incr:
echo $(date -d "+$lp_incr mins" +%s%N)
I am new to bash. I tried to find the answer to this, but couldn't quite find the solution. I am trying to subtract 86400 from $yesterday_date, but I end up with a "command not found" error.
(I know there are other methods of subtracting from a date, but I still want the solution to this problem.)
Script section:
yesterday_date=$(date +%s)
echo $yesterday_date
yesterday_date=$($yesterday_date-86400)
echo $yesterday_date
Script output:
1517335264
./myscript.sh: line 11: 1517335264-86400: command not found
What's the problem? Thanks.
Bash provides ((...)) for arithmetic operations. You don't have to use $ before ((..)).
yesterday_date=$(date +%s)
echo "$yesterday_date"
((yesterday_date-=86400))
echo "$yesterday_date"
You can let date do the math:
echo $(date -d "now -86400 seconds" +%s)
1517268350
or elimninate the magic number:
echo $(date -d "now -1 day" +%s)
1517268356
or even more literal:
echo $(date -d "yesterday" +%s)
1517268364
For fun, there is even a teatime option to the date command. ;)
I am making an adjustment a bash script of mine to output the ordinal part (st, nd, rd, th) of a day of month. I am trying to adjust it to be used within a date pattern in the date command.
Here is a simple test to determine if day of month from date command is an int:
dayOfMonth=$(date +"%d") && [[ ${dayOfMonth} =~ ^[0-9]+$ ]] && echo ${dayOfMonth} is an int || echo ${dayOfMonth} is NOT an int
Output is as I expect
01 is an int
Now I put that code into a script:
#!/bin/bash
[[ ${1} =~ ^[0-9]+$ ]] && echo ${1} is an int || echo ${1} is NOT an int
Seems OK:
dateTest.sh 12
12 is an int
But when I try to use it within a date command, the script is giving me conflicting output. echo sees 12 but the test is seeing %2
date --date='06/12/2012 07:21:22' +"`dateTest.sh %d`"
12 is NOT an int
To clarify my purpose, the end result of the script will be something like this:
#!/bin/bash
n=$(date +"%d")
if [ $# -ge 1 ] ; then
n=$1
if ! [[ $n =~ ^[0-9]+$ ]] ; then
echo Arg dateInteger [$dateInteger] must be an integer.
exit 1
fi
fi
if [ $n -ge 11 -a $n -le 13 ] ; then
echo "th"
else
case $(( $n%10 )) in
1)
echo st
;;
2)
echo nd
;;
3)
echo rd
;;
*)
echo th
;;
esac
fi
So that I can it like this:
date --date='06/12/2012 07:21:22' +"%A, %d`dateTest.sh %d` of %B %Y, %I:%M:%S %p"
which would output
Tuesday, 12th of June 2012, 07:21:22 AM
Finished script re-write. Thanks to input from #GordonDavisson, I completed my script re-write: http://pastebin.com/xZ1afqqC. Now it either outputs just the ordinal from an integer, or will output a fully formatted date where you can use standard format strings from date with the addition of "%O" for the ordinal.
You're doing things in the wrong order -- you have to turn "%d" into an integer (the day of the month) before passing it to your script, not after. Consider the command:
date --date='06/12/2012 07:21:22' +"`dateTest.sh %d`"
What this does is run dateTest.sh %d, i.e. it passes "%d" as the argument to your script. The script naturally outputs "%d is not an int". This is then used as the format string for the date command, i.e. date --date='06/12/2012 07:21:22' +"%d is not an int". The date command replaces the "%d" part with the day number, and leaves the rest alone, giving "12 is not an int".
In order to make this work, you have to get the day number first, then pass that to your script. Something like this:
dateTest.sh "$(date --date='06/12/2012 07:21:22' +"%d")"
Unfortunately, your end result script also wants a bunch of other date formatting done that can't be passed to the dateTest script. I think in that case it'd be best to do it in stages:
dayWithSuffix="$(dateTest.sh "$(date --date='06/12/2012 07:21:22' +"%d")")"
date --date='06/12/2012 07:21:22' +"%A, $dayWithSuffix of %B %Y, %I:%M:%S %p"
BTW, several general scripting suggestions:
Send error/debug output to stderr, not stdout, so it doesn't get confused with the script's regular output (part of the problem here). For example, echo "${1} is NOT an int" >&2
Speaking of which, put strings that contain variables in double-quotes (as I did in that last example) to avoid weird misparsing of whitespace, wildcards, etc. Your result script, for example, contains echo Arg dateInteger [$dateInteger] must be an integer. -- you probably don't realize that under certain circumstances the [$dateInteger] part will be replaced by a list of filenames.
Finally, use $( ... ) instead of backquotes. In most cases they're equivalent, but the parenthesis version is easier to read and avoids some weird parsing oddities of the contents. Notice how I nested two such expressions in the assignment to dayWithSuffix? That's much trickier to get right with backquotes.