(MacOS Terminal). How to produce a readable Epoch time from terminal - macos

I am trying to give a command to a friend who has been having account passwords changed. He is trying to determine a way to figure out when the password was last changed. I was able to give him this command, that is working in MacOS terminal, but I want to make it a bit nicer by providing a readable answer. Here is the command:
dscl . read /Users/username accountPolicyData | grep -A1 SetTime
which results in something like this:
<key>passwordLastSetTime</key>
<real>1670348364.4110398</real>
This command is pulling the reset date and time great, but him having to search out an epoch time calculator may be a bit over his head. My question:
Do any of you have any idea how I could strip out the bracketed text and convert the epoch time from the commandline? I'm happy to drop the title line if that helps if doing so would allow a numerical conversion that is readable.
Thanks for any suggestion you may have.

You can use defaults to read plist :
#!/bin/bash
file=$(mktemp /tmp/XXXXXXXX.plist)
dscl . read /Users/username accountPolicyData | tail -n +2 > $file
c=$(defaults read $file passwordLastSetTime)
date -r ${c%.*} '+%Y-%m-%d %H:%M:%S'
rm $file

You can use the following command to extract the epoch time and convert it to a human-readable date and time:
dscl . read /Users/username accountPolicyData | grep -A1 passwordLastSetTime | awk '/real/ {print strftime("%c",$2)}'
Explanation:
dscl . read /Users/username accountPolicyData is the same as before, it retrieves the account policy data for the specified username.
grep -A1 passwordLastSetTime filters the output to show only the line containing passwordLastSetTime and the next line.
awk '/real/ {print strftime("%c",$2)}' is an awk script that processes the filtered output. The script matches the line that contains real, extracts the second field ($2), and converts it from an epoch time to a human-readable date and time using the strftime function. The %c format string for strftime specifies a locale-specific date and time format.

Related

Bash: Obtain epoch time from date time string taken from file using awk

First of all, sorry as the title might not be a good one. Actually can't really think of a good title but I'll try to explain as much as I can here, so here goes,
I have a file called timeInfo which contains Date Time string in the following format,
2018-06-05 00:35:51 Controller shutdown process initiated
2018-06-05 05:32:22 Controller startup process initiated
...
...
Now what I'm trying to do is, I need to get this time and convert it into EPOCH and store it into a temporary file tempFile, what I've tried so far is ...
//$file points to **timeInfo** file
echo `grep 'Controller startup' $file | date -d "`awk '{ print $1,$2 }'`" >> $TEMP_FILE`
On using this I get the following error,
command substitution: line 73: unexpected EOF while looking for matching `"'
Then I tried a different approach and used the following code,
echo `grep "Controller startup" $file | awk '{print $1,$2}' >> $TEMP_FILE`
With this I get a file tempFile with the following info,
2018-06-06 00:35:31
2018-06-06 00:51:32
Which seems to be much better but I need to have it in EPOCH! Is there a way I can change the above script to save date time string in EPOCH format inside tempFile.
Hoping to hear your suggestion! Thank you
this may be what you want, needs gawk
$ awk '{t=$1 FS $2; gsub(/[-:]/," ",t); print mktime(t)}' file
1528173351
1528191142
or perhaps this
$ awk '/Controller (startup|shutdown)/{t=$1 FS $2;
gsub(/[-:]/," ",t);
print mktime(t)}' file
cat logfile|awk '{print($1,$2)}' |xargs -n 1 -I_ date +'%s' --date=_
Cat the file. Then awk the first two fields. and the using "xargs -n 1" passing one one data at a time to the date command and the using %s to get epoch.

Shell command to add a column to data (via another function)

I have data like
1234567890.123 'time1'
2345678901.234 'time2'
3456789012.345 'time3'
where the first number represents the epoch and I'd like to append a column with a human readable date. So something like cut -c 1-10 | xargs -I {} date -r {} is close but I'd like to keep around the other data on the line.
What's the simplest way to do this?
I am not sure if your data is just a string or something else, but if it is a string, you could just grep the first 10 numbers with grep and regex, convert to the readable date and append to the original string.
input="1234567890.123 'time1'"
readable="#$(echo $input| grep -oP '^[0-9]{10}')"
output="$input $(date -d $readable)"
I am using # and -r for the conversion but this should work fine with the -r option too.

Add file date to file name in bash

I'm looking for a programmatic way to add a file's date to the filename. I'm on a Mac, Yosemite (10.10).
Using Bash, I have put a fair amount of effort into this, but just too new to get there so far. Here's what I have so far:
#!/bin/bash
#!/bin/bash
(IFS='
'
for x in `ls -l | awk '{print$9" "$7"-"$6"-"$9}'`
do
currentfilename=$(expr "$x" : '\($substring\)')
filenamewithdate=$(expr "$x" : '.*\($substring\)')
echo "$currentfilename"
echo "$filenamewithdate"
done)
The idea here is to capture detailed ls output, use awk to capture the strings for the columns with the filename ($9), and also date fields ($7 and $6), then loop that output to capture the previous filename and new filename with the date to mv the file from old filename to new. The awk statement adds a space to separate current filename from new. The echo statement is there now to test if I am able to parse the awk ouput. I just don't know what to add for $substring to get the parts of the string that are needed.
I have much more to learn about Bash scripting, so I hope you'll bear with me as I learn. Any guidance?
Thanks.
Looking at the stat man page, you'd want:
for file in *; do
filedate=$(stat -t '%Y-%m-%dT%H:%M:%S' -f '%m' "$file")
newfile="$file-$filedate"
echo "current: $file -> new: $newfile"
done
Adjust your preferred datetime format to your taste.
You could save a line with
for file in *; do
newfile=$(stat -t '%Y-%m-%dT%H:%M:%S' -f '%N-%m' "$file")

Getting the creation date of a file on Cygwin

I'm trying to get the creation date of a file using console commands. I've managed to use this:
stat -c "%w" file
which outputs the date and time:
2015-05-01 09:33:22.503525000 -0400
But I'd like to extract only the date (without the time) from the result. Is there a way to do this using only stat, or do I have to separate the result using another command? And what might that command be?
Try this:
stat -c "%w" file | cut -d" " -f1
The output of stat will be piped into cut and the string will be cut at the first concurrence of a white space.
Assuming you are using bash:
date -d "#$(stat -c %W file)" +%F
Will do the trick. %W on stat returns the epoch date, date +%F converts it to a YYYY-MM-DD format.

Shell Script String Manipulation

I'm trying to replace an epoch timestamp within a string, with a human readable timestamp. I know how to convert the epoch to the time format I need (and have been doing so manually), though I'm having trouble figuring out how to replace it within the string (via script).
The string is a file name, such as XXXX-XXX-2011-01-25-3.6.2-record.pb.1296066338.gz (epoch is bolded).
I've been converting the timestamp with the following gawk code:
gawk 'BEGIN{print strftime("%Y%m%d.%k%M",1296243507)}'
I'm generally unfamiliar with bash scripting. Can anyone give me a nudge in the right direction?
thanks.
You can use this
date -d '#1296066338' +'%Y%m%d.%k%M'
in case you don't want to invoke awk.
Are all filenames the same format? Specifically, "." + epoch + ".gz"?
If so, you can use a number of different routes. Here's one with sed:
$ echo "XXXX-XXX-2011-01-25-3.6.2-record.pb.1296066338.gz" | sed 's/.*\.\([0-9]\+\)\.gz/\1/'
1296066338
So that extracts the epoch, then send it to your gawk command. Something like:
#!/bin/bash
...
epoch=$( echo "XXXX-XXX-2011-01-25-3.6.2-record.pb.1296066338.gz" | sed 's/.*\.\([0-9]\+\)\.gz/\1/' )
readable_timestamp=$( gawk "BEGIN{print strftime(\"%Y%m%d.%k%M\",${epoch})}" )
Then use whatever method you want to replace the number in the filename. You can send it through sed again, but instead of saving the epoch, you would want to save the other parts of the filename.
EDIT:
For good measure, a working sample on my machine:
#!/bin/bash
filename="XXXX-XXX-2011-01-25-3.6.2-record.pb.1296066338.gz"
epoch=$( echo ${filename} | sed 's/.*\.\([0-9]\+\)\.gz/\1/' )
readable_timestamp=$( gawk "BEGIN{print strftime(\"%Y%m%d.%k%M\",${epoch})}" )
new_filename=$( echo ${filename} | sed "s/\(.*\.\)[0-9]\+\(\.gz\)/\1${readable_timestamp}\2/" )
echo ${new_filename}
You can use Bash's string manipulation and AWK's variable passing to avoid having to make any calls to sed or do any quote escaping.
#!/bin/bash
file='XXXX-XXX-2011-01-25-3.6.2-record.pb.1296066338.gz'
base=${file%.*.*} # XXXX-XXX-2011-01-25-3.6.2-record.pb
epoch=${file#$base} # 1296066338.gz
epoch=${epoch%.*} # 1296066338
# we can extract the extension similarly, unless it's safe to assume it's ".gz"
humantime=$(gawk -v "epoch=$epoch" 'BEGIN{print strftime("%Y%m%d.%k%M",epoch)}')
newname=$base.$humantime.gz
echo "$newname"
Result:
XXXX-XXX-2011-01-25-3.6.2-record.pb.20110126.1225.gz

Resources