Subtracting time from file creation/modification date in OSX - macos

I am trying to shift the dates of a series of files by 9 hours. I've reached as far as this:
for i in *.MOV; do touch -r "$i" -d "-9 hours" "$i"; done
This should work in recent systems, but the touch command in OSX seems to be a bit outdated and not to support the -d switch.
I'm using Snow Leopard. Any idea on the best option for doing this with a single line command? I don't want to create a script for this.

Ok, sorted it out. OSX comes with a gtouch command, that knows the -d switch. It's part of GNU coreutils. See the comments below for information regarding availability on specific MacOS versions.
For more information on using relative dates with the -d switch see the manual.

Looking at the Wikipedia Page for Touch, it appears you're accustomed to the GNU version of Touch. Which MacOS isn't using.
For what you want to do, look into the "SetFile" command, which gets installed with XCode tools. You have -d and -m options, which reset the Created and Modified dates & times respectively.
http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/SetFile.1.html

Donno OS X, but it should be easy enough to
get curr time stamp on the file
convert it to seconds
subtract 9 hours (9*60*60 secs) from it
convert it back to the format accepted by touch's -t option
run touch command
All this of course can be done in a single for loop on command line.
Here are simple examples from WikiPedia showing back and forth conversion.
# To convert a specific time stamp to Unix epoch time (seconds since 1970-01-01):
date +"%s" -d "Fri Apr 24 13:14:39 CDT 2009"
# 1240596879
# To convert Unix epoch time (seconds since 1970-01-01) to a human readable format:
date -d "UTC 1970-01-01 1240596879 secs"
# Fri Apr 24 13:14:39 CDT 2009
# Or:
date -ud #1000000000
# Sun Sep 9 01:46:40 UTC 2001
# or: Haven't tested this but should work..
date -d #1000000000 +%y%m%d%%H%M%S
# 010909014640

Related

How to get last Week's date in bash SunOS

Here is my issue: I have a backup bash script that needs to access a folder with a date in its name for example : backup_01072022 .
I used date=`TZ=GMT+24 date +%d%m%Y` when i needed to access the backup folder of yesterday.
Now I want to access the backup folder of last week :
date=`TZ=GMT+168 date +%d%m%Y` , it doesn't work , it show today's date.
I read that TZ doesn't work for a value above +144.
Is there any other way of manipulating dates in SunOS 6.8 ?
Notes :
SunOS 6.8
version of the date util : 8.5
version of bash : 4.1.11(2)-release
This'll depend on the version of date on your system.
With GNU date (v 8.26):
$ TZ=GMT date '+%d%m%Y'
06072022 # today
$ TZ=GMT date '+%d%m%Y' -d 'last week'
29062022
$ TZ=GMT date '+%d%m%Y' -d '7 days ago'
29062022
NOTE: I'll leave it up to OP to determine if the explicit TZ setting should be adjusted (or used at all)
I seem to recall SunOS comes with Perl, so if you don't have a date that supports --date="...", you should be able to do:
date=$(perl -MPOSIX -e '
print POSIX::strftime "%d%m%Y", localtime time-(60*60*24*7)
')
Thanks to the helpful commments and answers I was able to make it work using :
/usr/gnu/bin/date -d "last week" '+%d%m%Y'
It turns out I was not using the GNU date util until I specified it explicitly, and that's neither --date nor -d was working for me.
I still can't figure out what date util I was using by default if not GNU date.

UNIX Shell Calculate hours difference between two timestamps

I have two timestamps in formats :
Timestamp 1 (Variable - RunStartDate): Thu May 3 14:12:54 CDT 2018
Timestamp 2 (Variable - RunEndDate): Thu May 3 18:11:46 CDT 2018
I want the difference of number of hours between these two timestamps in UNIX shell. (I.e. RunEndDate - RunStartDate in hours)
Please help, I am new to UNIX and it is throwing me errors when I just try to subtract the two.
You have a few options here, such as calling out to Perl or Python and using a date/time library to do the math for you. Another option is to use the date program to convert the dates to seconds, subtract the values, and then convert back to hours. Unfortunately, you can't do floating-point math in Bash, so we'll have to call out to a helper program to do that, too.
START=$(date -d "$RunStartDate" +"%s")
END=$(date -d "$RunEndDate" +"%s")
HOURS=$(bc -l <<< "($END - $START) / 3600")
Note that this will only work on GNU systems (e.g. Linux).

How to find the date using internet (ie ntp) from bash?

How can I learn date and time from the internet using bash without installing anything extra.
I am basically looking for an equivalent of bash $ date, but using an NTP (or any other way) to get the correct date and time from the internet. All the methods I find (such as ntpd) are meant to correct the system time, which is not my purpose.
date has a lot of options for formatting, but I'm assuming that you just want the date and time:
ntpdate -q time.google.com | sed -n 's/ ntpdate.*//p'
(or any other time server)
If you have ntpd installed & configured then you can use the NTP Query command ntpq -crv which will return;
associd=0 status=04ff leap_none, sync_uhf_radio, 15 events, stale_leapsecond_values,
version="ntpd 4.2.6p5#1.2349-o Mon Feb 6 07:22:46 UTC 2017 (1)",
processor="x86_64", system="Linux/4.10.13-1.el6.elrepo.x86_64", leap=00,
stratum=1, precision=-23, rootdelay=0.000, rootdisp=1.000, refid=PPS,
reftime=dd2c9f10.f25911ee Wed, Aug 2 2017 19:57:20.946,
clock=dd2c9f11.f4251b0a Wed, Aug 2 2017 19:57:21.953, peer=6516, tc=4,
mintc=3, offset=-0.005, frequency=-17.045, sys_jitter=0.110,
clk_jitter=0.007, clk_wander=0.003, tai=37, leapsec=201701010000,
expire=201706010000
You want the line starting clock which gives the time, date etc - you would be best parsing this out with awk or something if you just want the date stamp rather then everything else.
You do not need to be a root user to run the command. It won't set anything, but will query your local server (presuming your running ntp) and present the details.

Subtract 20 month from user provided date in yymm in unix

oldest_year_month_temp=201602
NUM_PART_RETAIN=20
oldest_year_month=`date --date="$(oldest_year_month_temp +%Y%m) - $NUM_PART_RETAIN month" "+%Y%m"`
Date is not coming as expected.
One easy way to do it would be to simply append a 01 to your input of yymm to provide a format date -d could read as the starting date, then simply subtract 20 months and output the resulting date in %y%m format. For example, if you provide the date 9910 (Oct. 1999), you can do:
$ date -d "991001 - 20 months" +%y%m
9802
Which returns Feb. 1998 (20 months earlier)
(note: the $ above just indicates a command by a normal user as opposed to # indicating a command by the super user (e.g. root))
Inside the $(...) there must be a command, e.g. $(date ...).
This should have been obvious from the error message you got, which was probably oldest_year_month_temp: no such command.
When reading from a variable, you must write a $ before its name.

Text-Message Gateways & Incrementing Bash Variable Daily

I have a bash script that is sending me a text daily, for 100 days.
#! /bin/bash
EMAIL="my-phone-gateway#address.net"
MESSAGE="message_content.txt"
mail $EMAIL < $MESSAGE
Using crontab, I can have the static $MESSAGE sent to me every day.
Other than hard-coding 100 days of texts ;)
How could I implement a variable counter such that I can have my texts say:
"Today is Day #1" on the first day, "Today is Day #2" on the second day, etc. ?
Note: The location of the requested text within the $MESSAGE file doesn't matter. Last line, first line, middle, etc.
The only requirement for an answer here is that I know what day it is relative to the first, where the first day is the day the script was started.
Of course, bonus awesome points for the cleanest, simplest, shortest solution :)
For our nightly build systems, I wrote a C program that does the calculation (using local proprietary libraries that store dates as a number of days since a reference date). Basically, given a (non-changing) reference date, it reports the number of days since the reference date. So, the cron script would have a hard-wired first day in it, and the program would report the number of days since then.
The big advantage of this system is that the reference date doesn't change (very often), so the script doesn't change (very often), and there are no external files to store information in.
There probably are ways to achieve the same effect with standard Unix tools, but I've not sat down and worked out the portable solution. I'd probably think it terms of using Perl. (The C program only works up to 2999 CE; I left a note in the code for people to contact me about 50 years before it becomes a problem for the Y3K fix. It is probably trivial.)
You could perhaps work in terms of Unix timestamps...
Create a script 'days_since 1234567890' which treats the number as the reference date, gets the current time stamp (from date with appropriate format specification; on Linux, date '+%s' would do that job, and it works on Mac OS X too), takes the difference and divides by 86,400 (the number of seconds in a day).
refdate=1234567890
bc <<EOF
scale=0
($(date '+%s') - $refdate) / 86400
EOF
An example:
$ timestamp 1234567890
1234567890 = Fri Feb 13 15:31:30 2009
$ timestamp
1330027280 = Thu Feb 23 12:01:20 2012
$ refdate=1234567890
$ bc <<EOF
> scale=0
> ($(date '+%s') - $refdate) / 86400
> EOF
1104
$
So, if the reference date was 13th Feb 2009, today is day 1104. (The program bc is the calculator; its name has nothing to do with Anno Domini or Before Christ. The program timestamp is another homebrew of mine that prints timestamps according to a format that can be specified; it is a specialized variant of date originally written in the days before date had the functionality, by which I mean in the early 1980s.)
In a Perl one-liner (assuming you specify the reference date in your script):
perl -e 'printf "%d\n", int((time - 1234567890)/ 86400)'
or:
days=$(perl -e 'printf "%d\n", int((time - 1234567890)/ 86400)')
The only way to accomplish this would be to store the date in a file, and read from that file each day. I would suggest storing the epoch time.
today=$(date +%s)
time_file="~/.first_time"
if [[ -f $time_file ]]; then
f_time=$(< "$time_file")
else
f_time=$today
echo "$f_time" > "$time_file"
fi
printf 'This is day: %s\n' "$((($today - $f_time) / 60 / 60 / 24))"
Considering that your script is running only once a day, something like this should work:
#!/bin/bash
EMAIL="my-phone-gateway#address.net"
MESSAGE="message_content.txt"
STFILE=/tmp/start.txt
start=0
[ -f $STFILE ] && start=$(<$STFILE)
start=$((start+1))
MESSAGE=${MESSAGE}$'\n'"Today is Day #${start}"
echo "$start" > $STFILE
mail $EMAIL < $MESSAGE
A simple answer would be to export the current value to an external file, and read that back in again later.
So, for example, make a file called "CurrentDay.dat" that has the number 1 in it.
Then, in your bash script, read in the number and increment it.
e.g. your bash script could be:
#!/bin/bash
#Your stuff here.
DayCounter=$(<CurrentDay.dat)
#Use the value of DayCounter (i.e. $DayCounter) in your message.
DayCounter=$((DayCounter + 1))
echo $DayCounter > CurrentDay.dat
Of course, you may need to implement some additional checks to avoid something going wrong, but that should work as is.

Resources