linux touch relative time giving wrong result - bash

I'm using bash touch to change the date and time of a file. It works correctly if I simply specify the date and time. If, however, I use a relative time I get unexpected behavior.
$ date -R -r test.txt
Sat, 28 May 2022 02:56:22 -0400
$ touch -d '27 May 2022 05:31:12' test.txt
$ date -R -r test.txt
Fri, 27 May 2022 05:31:12 -0400
$ touch -d '27 May 2022 05:31:12 - 1 hour' test.txt
$ date -R -r test.txt
Fri, 27 May 2022 03:31:12 -0400
$ touch -d "27 May 2022 05:31:12 + 1 hour" test.txt
$ date -R -r test.txt
Fri, 27 May 2022 01:31:12 -0400
Note that although I asked for 1 hour earlier and then 1 hour later, it gave 2 hours earlier and 4 hours earlier respectively.
Any help would be appreciated.

When you do your touch, you do no specify the timezone. If you do, all your date arithmetic works ok.
EX:
$ touch -d '27 May 2022 05:31:12' test.txt
$ date -R -r test.txt
Fri, 27 May 2022 05:31:12 -0400
$
$ touch -d '27 May 2022 05:31:12 -0400 - 1 hour' test.txt
$ date -R -r test.txt
Fri, 27 May 2022 04:31:12 -0400

Related

Just trying to concatenate output from `aws s3 cp ...` with a date but date being gobbled

I have a bash script which logs what it does with aws s3, prefixing each log message with a date. When I try to prefix the output of the cp command, the date doesn't appear. The same thing works with rm...
This works
echo "$(date) $(aws s3 rm ${S3_BUCKET}${i})"
This only outputs the aws output
echo "$(date) $(aws s3 cp ${DUMP_FILE} ${S3_BUCKET})"
So I get something like this...
Sun Dec 16 09:30:21 GMT 2018 purging all but the latest 4 agent backups
Sun Dec 16 09:30:21 GMT 2018 rm <file>
Sun Dec 16 09:30:21 GMT 2018 delete: s3://<folder> (this is AWS output with my date prefix)
Sun Dec 16 09:30:22 GMT 2018 take backup
Sun Dec 16 09:30:22 GMT 2018 backup complete
upload: ./<file> to s3://<bucket> (where's the date prefix!)
I've tried it directly in the shell too with the same result

Run function on every prompt line with .bash_profile editing

I have the following PS1 command in my .bash_profile:
PS1="$(svn info 2>&1 | grep 'Relative URL' | awk '{print $NF}')"
So that the output of this command is presented in the prompt line.
But it is run once I start the terminal and it just stays there, instead of changing while I navigate through my directories. So it runs once and is left there.
How can I make it change as I am navigating my directories?
PROMPT_COMMAND
If set, the value is executed as a command prior to issuing each
primary prompt.
$ PROMPT_COMMAND=date
Sun Feb 21 13:35:21 EST 2016
$ echo a
a
Sun Feb 21 13:35:23 EST 2016
$ echo b
b
Sun Feb 21 13:35:24 EST 2016
$ PROMPT_COMMAND='PS1=`date +%H:%M`\ $\ '
13:35 $ sleep 60
13:36 $

Convert unix epoch time to human readable date on Mac OSX - BSD

On my Mac OSX, my bash script has a epoch time 123439819723. I am able to convert the date to human readable format by date -r 123439819723 which gives me Fri Aug 26 09:48:43 EST 5881.
But I want the date to be in mm/ddd/yyyy:hh:mi:ss format. The date --date option doesn't work on my machine.
Here you go:
# date -r 123439819723 '+%m/%d/%Y:%H:%M:%S'
08/26/5881:17:48:43
In a bash script you could have something like this:
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
dayOfWeek=$(date --date #1599032939 +"%A")
dateString=$(date --date #1599032939 +"%m/%d/%Y:%H:%M:%S")
elif [[ "$OSTYPE" == "darwin"* ]]; then
dayOfWeek=$(date -r 1599032939 +%A)
dateString=$(date -r 1599032939 +%m/%d/%Y:%H:%M:%S)
fi
To convert a UNIX epoch time with OS X date, use
date -j -f %s 123439819723
The -j prevents date from trying to set the system clock, and -f specifies the input format. You can add +<whatever> to set the output format, as with GNU date.
from command Shell
[aks#APC ~]$ date -r 1474588800
Fri Sep 23 05:30:00 IST 2016
[aks#APC ~]$ date -ur 1474588800
Fri Sep 23 00:00:00 UTC 2016
[aks#APC ~]$ echo "1474588800" | xargs -I {} date -jr {} -u
Fri Sep 23 00:00:00 UTC 2016
In case of Linux (with GNU coreutils 5.3+) it can be achieved using less keystrokes:
date -d #1608185188
#Wed Dec 16 22:06:28 PST 2020
On Mac one may need to install coreutils (brew install coreutils)
Combined solution to run on Mac OS.
Shell code:
T=123439819723
D=$(date -j -f %s $(($T/1000)) '+%m/%d/%Y:%H:%M:%S').$(($T%1000))
echo "[$T] ==> [$D]"
Output:
[123439819723] ==> [11/29/1973:11:50:19.723]
Or one line:
> echo 123439819723 | { read T; D=$(date -j -f %s $(($T/1000)) '+%m/%d/%Y:%H:%M:%S').$(($T%1000)); echo "[$T] ==> [$D]" }
[123439819723] ==> [11/29/1973:11:50:19.723]

display a line every two line (osX) zsh

I'd to display every two line, a line from a file. I've seen the sed -n 'f~d' awk and perl method. But the sed one doesn't work on osX (As I understood) and the two others are are interpreted languages which i can't use.
Can you help me ?
Here's an exemple :
output before :
-rw-r--r-- 1 mfassi-f 2013 22 Jul 17 12:36 test.sh
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test1.sh
-rw-r--r-- 1 mfassi-f 2013 22 Jul 17 12:36 test2.sh
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test3.sh
-rw-r--r-- 1 mfassi-f 2013 22 Jul 17 12:36 test4.sh
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test5.sh
-rw-r--r-- 1 mfassi-f 2013 22 Jul 17 12:36 test6.sh
output after :
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test1.sh
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test3.sh
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test3.sh
-rw-r--r-- 1 mfassi-f 2013 29 Jul 17 12:30 test5.sh
Here are two answers. One for a file, and one for command-line input.
['cause the question's changed ever so slightly, but these two seemed too similar to put as independent answers].
You can use zsh, ls, cut and paste to do this in a for loop. It's not the cleanest solution, but it does work (surprisingly).
for file in `ls -1 | paste - - | cut -f 1`
do
ls -l -d $file
done
We take the output of ls -1, then extract every second filename. (The way ls chooses to sort the files will have an impact here). Then, we do ls -l -d on each of these files. -d is necessary to stop ls from showing us the contents of $file, if $file is a directory. (Not sure if this is OS X specific, or if that's default POSIX ls behaviour).
Second answer: display every second line from a file.
If you're after a mostly zsh solution, you could do something like the following:
$ jot 8 0 7 >> sample.txt # Generate some numbers.
$ count=0 # Storage variable
$ for i in `cat sample.txt`
do
if [ $(( $count % 2 )) -eq 0 ] ; then
echo $i
fi
count=`expr $count + 1`
done
This displays every second line.
Notes:
- This leaves a variable count in your session afterwards (it's not clean).
- This fails badly if sample.txt does not contain a single word per line.
- I'm almost sure that the modulus comparison I do isn't the most efficient: I grabbed it from here.
- I say it's mostly zsh because it does rely on cat, but I'm not sure how to avoid that.
The OS X version of sed is frustrating. Using sed -n '0~2p' <filename> doesn't work because, in the BSD sed, -n does something different:
-n
By default, each line of input is echoed to the standard output after all of the commands have been applied to it. The -n option suppresses this behavior.
I'd highly recommend installing GNU sed, which can be done using Homebrew:
brew install gnu-sed
And then you can use:
gsed -n '0~2p' filename # Display the 2nd, 4th etc
gsed -n '1~2p' filename # Display the 1st, 3rd etc.

How to convert UTC timestamp in seconds to human readable local time in a shell script?

Given UTC timestamp in seconds 1361322102.430 How do I convert it to human readable local time in a shell script?
Same moment in time at 1361322102.430 UTC seconds
shown in local time zone
$ date -d #1361322102.430
Tue Feb 19 20:01:42 EST 2013
shown in UTC time zone
$ date -d #1361322102.430 -u
Wed Feb 20 01:01:42 UTC 2013
For more details → $ info coreutils 'date invocation'
GNU:
$ date -d #1361414562.231
Wed Feb 20 18:42:42 PST 2013
Most BSDs:
$ date -r 1361414562.231
Wed Feb 20 18:41:38 PST 2013

Resources