UNIX stat time format - bash

Is it possible to format the time output of stat? I am using
stat -c '%n %A %z' $filename
in a bash script, but its time format is not what I want. Is it possible to change this format in the command, or would I have to manually do it later?
An example output follows:
/lib drwxr-xr-x 2010-11-15 04:02:38.000000000 -0800

You can simply strip of the decimal portion like this:
stat -c '%n %A %z' "$filename" | sed 's/\(:[0-9]\{2\}\)\.[0-9]* /\1 /'
Edit:
Here's another way to truncate the decimal portion:
stat -c '%n %A %.19z' "$filename"
This depends on the date being 19 characters long: 2010-11-15 04:02:38

You could try something like:
date -d "1970-01-01 + $(stat -c '%Z' $filename ) secs"
Which gives you only the date. You can format the date using date's formatting options (see man date), for example:
date -d "1970-01-01 + $(stat -c '%Z' $filename ) secs" '+%F %X'
This doesn't give you the name and permissions but you may be able to do that like:
echo "$(stat -c '%n %A' $filename) $(date -d "1970-01-01 + $(stat -c '%Z' $filename ) secs" '+%F %X')"

Related

Bash script check time differnce between two directory

I am looking for a bash script to who check time difference between two directory? But in $oldtime i can`t get only 20:09:24 i get this "20:09:24.660157390".
How can i get only hours:min only.
#!/bin/bash
oldtime=$(stat -c %y /mnt/dir1| awk '{print $2}' )
ctime=$(date | awk '{print $4}')
DIFF=$($oldtime-$ctime)
if [ $DIFF > 600 ]; then
echo "This directory have more that 10 min"
fi
You could shave off the extra suffix,
but that won't really help you.
20:09:24 - $ctime is not going to work,
because "20:09:24" is not a number.
You have several other syntax errors as well.
To calculate the difference between dates,
you need to work with seconds.
oldseconds=$(stat -c %Y /mnt/dir1)
newseconds=$(date +%s)
if (((newseconds - oldseconds) / 60)); then
echo "This directory have more than 10 min"
fi
Use epoch timestamp and date for converting to that format.
$ date +%H:%M -d #`stat -c %Y /tmp/`
19:19
But it's not recommended to use this format for comparing. Use unix timestamps instead:
if [ $(( $(date +%s) - $(stat -c %Y /tmp) )) -gt 600 ]; then
echo "This directory have more that 10 min"
fi

Shell Script for Yesterdays Date

I have tried adding -d "yesterday" but I haven't had any luck getting it to work. Here is what I have for the whole script:
#! /bin/bash
saveDir="TJ"
dd=$(date +"%m-%d-%Y")
for file in *.csv ; do
saveName="${saveDir}/TJ ${dd}.csv"
cut -d',' -f2,14 "$file" > "$saveName"
done
how do I get dd to output yesterdays date instead of the current date?
EDIT: This is what I have now
#! /bin/bash
saveDir="TJ"
dd=$(date --date='yesterday' +'%m-%d-%Y')
for file in *.csv ; do
saveName="${saveDir}/TJ ${dd}.csv"
cut -d',' -f2,14 "$file" > "$saveName"
done
the above is saving the file as TJ .csv but I'm not sure what was done incorrectly
I think you want to use -
$ cat test.sh
#!/bin/bash
dd=$(date --date='yesterday' +'%m-%d-%Y')
echo $dd
$ ./test.sh
12-31-2013
or you could use
$ date -d '1 day ago' +'%m-%d-%Y'
12/31/2013
And for tomorrow -
$ date -d '1 day' +'%m-%d-%Y'
01/02/2014
or
$ date --date='tomorrow'
Thu Jan 2 21:25:00 EST 2014
Get today's date in seconds since epoch. Subtract 86400 to get to yesterday. Then convert yesterday to the string format you want.
today=`date +"%s"`
yesterday=`expr $today - 86400`
dd=`date --date="#${yesterday}" +"%m-%d-%Y"`
Try this
yday=$(date --date yesterday "+%d-%m-%Y")
echo $yday
And If you works in Linux
yday=$(date -d "-1 days" +"%d-%m-%Y")
echo $yday
I tried date -d "yesterday" +%m-%d-%Y on my Linux, it worked fine.
If you are on unix platform, you cannot use -d,
you can get yesterday's date using perl, this is how I do using perl
dd=$(perl -e '($a,$b,$c,$day,$mon,$year,$d,$e,$f) = localtime(time-86400);printf "%02d-%02d-%4d",$day, $mon+1, $year+1900')
echo $dd
01-01-2014
NewDate=`date +"%A %d %B %Y" --date="-1 day"`
echo $NewDate
this will give your yesterday's date (-1)
This will give you tomorrow's date (+1)
even you can check for any values like (+/-) days

how to convert 2012-05-03T25:00:00 to 2012-05-04T01:00:00 in unix

I am not sure how this will be done in unix can anybody help/suggest to convert
2012-05-03T25:00:00 to 2012-05-04T01:00:00 in Unix command/script
In my file I have more than one occurrence with different times those needs to converted to next day
2012-05-03T25:00:00 to 2012-05-04T01:00:00
2012-05-03T26:50:00 to 2012-05-04T02:50:00
2012-05-03T31:59:59 to 2012-05-04T07:59:59
etc
I tried it but somehow sed is not working
Date.txt
2009-09-12T05:18:#00#+10:00,D,
2009-09-12T05:24:00+10:00,2009-09-12T05:24:#00#+10:00,D,
2009-09-12T05:25:00+10:00,2009-09-12T05:25:#00#+10:00,D,
2009-09-12T05:27:00+10:00,2009-09-12T05:27:#00#+10:00,D,
2009-09-12T30:29:00+10:00,2009-09-12T05:29:#00#+10:00,D,
2009-09-12T29:31:00+10:00,2009-09-12T05:31:#00#+10:00,D,
2009-09-12T28:33:00+10:00,,D,
2009-09-12T27:00:#00#+10:00,U,
2009-09-12T26:01:00+10:00,2009-09-12T05:01:#00#+10:00,U,
2009-09-12T24:04:00+10:00,2009-09-12T05:04:#00#+10:00,U,
2009-09-12T24:59:59+10:00,2009-09-12T05:06:#00#+10:00,U,
2009-09-12T30:08:00+10:00,2009-09-12T05:08:#00#+10:00,U,
2009-09-12T31:59:59+10:00,2009-09-12T05:10:#00#+10:00,U,
2009-09-12T05:17:00+10:00,,U,
2009-09-12T25:25:#00#+10:00,D,
script.sh
awk -F"T" -v OFS=',' '{print $1}' date.txt > tmpdate
uniq -d tmpdate > tmpuniq
rm tmpdate
date1=`cat tmpuniq`
date2=`date --set="$date1" +%F`
date3=$(date --date="$date2" -d "+1 day" +"%F")
T1=$date2+"T24"
T2=$date3+"T00"
echo $T1
echo $T2
dos2unix date.txt
#sed -i 's/$T1/$T2/g' date.txt > test.txt
#sed -i 's/"$T1"/"$T2"/g' date.txt > test.txt
sed -i 's/'$T1'/'$T2'/g' date.txt
Any help much appreciated
If you have Tcl on your system, the clock command makes it pretty easy:
set t 2012-05-03T31:59:59
lassign [split $t T] date time
lassign [split $time :] hour min sec
set base [clock scan $date -format %Y-%m-%d]
set new [clock add $base $hour hours $min minutes $sec seconds]
puts [clock format $new -format %Y-%m-%dT%T] ;# -> 2012-05-04T07:59:59
Update for cygwin:
first, using the cygwin installer, install the version 8.5.x of the "tcl" package (located in the Interpreters category). Then, you can do this
normalize_time() {
printf '
lassign [split "%s" T] date time
lassign [split $time :] hour min sec
set base [clock scan $date -format %%Y-%%m-%%d]
set new [clock add $base $hour hours $min minutes $sec seconds]
puts [clock format $new -format %%Y-%%m-%%dT%%T]
' "$1" | tclsh
}
normalize_time 2012-05-03T31:59:59
You will basically need to parse the erroneous time specification, convert everything to seconds, add it back together, and convert it back to a proper date.
date -d "date" +%s produces seconds since January 1, 1970. date -d #1234567890 converts a date in this format back to a regular human-readable date.
#!/bin/sh
IFS=T:
while read date hh mm ss; do
basedate=$(date -d "$date" +%s)
date -d #$(echo "$basedate+($hh*60*60)+($mm*60)+$ss" | bc) +%FT%T
done <<EOF
2012-05-03T25:00:00
2012-05-03T26:50:00
2012-05-03T31:59:59
EOF
I didn't have bc on this computer so I replaced my original attempt with a small awk script, but it's not very readable.
awk 'END { print '"$basedate"'+('"$hh"'*60*60)+('"$mm"'*60)+'"$ss"'}' </dev/null
If you don't have a recent enough version of GNU date, you can find some alternative ways at http://www.antonolsen.com/2006/04/06/bash-convert-unix-timestamp-to-a-date/
finally I got a solution with a bug (if date is last day of the month then this will not work but I can live with that)
and did a clumsy job
date1=`cat date.txt | awk -F. '{print substr($1,1,10)}'|uniq |head -1`
echo $date1
date2=$date1"T24"
date21=$date1"T25"
date22=$date1"T26"
date23=$date1"T27"
date24=$date1"T28"
date25=$date1"T29"
date26=$date1"T30"
date27=$date1"T31"
date3=$(date --date="$date1" -d "+1 day" +"%F")
echo $date2
cat date.txt | grep "$date2"
tmpdate=`echo $date1 | sed -e 's/-//g'`
echo $tmpdate
date4=`echo $(date -d $(echo \`expr $tmpdate + 1\`F) +"%F")`
echo $date4
date41=$date4"T00"
date42=$date4"T01"
date43=$date4"T02"
date44=$date4"T03"
date45=$date4"T04"
date46=$date4"T05"
date47=$date4"T06"
date48=$date4"T07"
sed -i 's/'$date2'/'$date41'/g' date.txt
sed -i 's/'$date21'/'$date42'/g' date.txt
sed -i 's/'$date22'/'$date43'/g' date.txt
sed -i 's/'$date23'/'$date44'/g' date.txt
sed -i 's/'$date24'/'$date45'/g' date.txt
sed -i 's/'$date25'/'$date46'/g' date.txt
sed -i 's/'$date26'/'$date47'/g' date.txt
sed -i 's/'$date27'/'$date48'/g' date.txt
If anyone wants to improve this script please go ahead.
Once again thanks to all.
First, use cat 'yourfile' to open it. Then do a loop on each line. Then use grep and cut. That's really simple to do and the most efficient way for you to learn is to go through the man pages of cat, grep, and cut.
Hope it'll help.

YYYY-MM-DD format date in shell script

I tried using $(date) in my bash shell script, however, I want the date in YYYY-MM-DD format.
How do I get this?
In bash (>=4.2) it is preferable to use printf's built-in date formatter (part of bash) rather than the external date (usually GNU date).
As such:
# put current date as yyyy-mm-dd in $date
# -1 -> explicit current date, bash >=4.3 defaults to current time if not provided
# -2 -> start time for shell
printf -v date '%(%Y-%m-%d)T\n' -1
# put current date as yyyy-mm-dd HH:MM:SS in $date
printf -v date '%(%Y-%m-%d %H:%M:%S)T\n' -1
# to print directly remove -v flag, as such:
printf '%(%Y-%m-%d)T\n' -1
# -> current date printed to terminal
In bash (<4.2):
# put current date as yyyy-mm-dd in $date
date=$(date '+%Y-%m-%d')
# put current date as yyyy-mm-dd HH:MM:SS in $date
date=$(date '+%Y-%m-%d %H:%M:%S')
# print current date directly
echo $(date '+%Y-%m-%d')
Other available date formats can be viewed from the date man pages (for external non-bash specific command):
man date
Try: $(date +%F)
The %F option is an alias for %Y-%m-%d
You can do something like this:
$ date +'%Y-%m-%d'
$(date +%F)
output
2018-06-20
Or if you also want time:
$(date +%F_%H-%M-%S)
can be used to remove colons (:) in between
output
2018-06-20_09-55-58
You're looking for ISO 8601 standard date format, so if you have GNU date (or any date command more modern than 1988) just do: $(date -I)
date -d '1 hour ago' '+%Y-%m-%d'
The output would be 2015-06-14.
With recent Bash (version ≥ 4.2), you can use the builtin printf with the format modifier %(strftime_format)T:
$ printf '%(%Y-%m-%d)T\n' -1 # Get YYYY-MM-DD (-1 stands for "current time")
2017-11-10
$ printf '%(%F)T\n' -1 # Synonym of the above
2017-11-10
$ printf -v date '%(%F)T' -1 # Capture as var $date
printf is much faster than date since it's a Bash builtin while date is an external command.
As well, printf -v date ... is faster than date=$(printf ...) since it doesn't require forking a subshell.
I use the following formulation:
TODAY=`date -I`
echo $TODAY
Checkout the man page for date, there is a number of other useful options:
man date
if you want the year in a two number format such as 17 rather than 2017, do the following:
DATE=`date +%d-%m-%y`
I use $(date +"%Y-%m-%d") or $(date +"%Y-%m-%d %T") with time and hours.
I used below method. Thanks for all methods/answers
ubuntu#apj:/tmp$ datevar=$(date +'%Y-%m-%d : %H-%M')
ubuntu#apj:/tmp$ echo $datevar
2022-03-31 : 10-48
Whenever I have a task like this I end up falling back to
$ man strftime
to remind myself of all the possibilities for time formatting options.
Try to use this command :
date | cut -d " " -f2-4 | tr " " "-"
The output would be like: 21-Feb-2021
#!/bin/bash -e
x='2018-01-18 10:00:00'
a=$(date -d "$x")
b=$(date -d "$a 10 min" "+%Y-%m-%d %H:%M:%S")
c=$(date -d "$b 10 min" "+%Y-%m-%d %H:%M:%S")
#date -d "$a 30 min" "+%Y-%m-%d %H:%M:%S"
echo Entered Date is $x
echo Second Date is $b
echo Third Date is $c
Here x is sample date used & then example displays both formatting of data as well as getting dates 10 mins more then current date.
You can set date as environment variable and later u can use it
setenv DATE `date "+%Y-%m-%d"`
echo "----------- ${DATE} -------------"
or
DATE =`date "+%Y-%m-%d"`
echo "----------- ${DATE} -------------"
echo "`date "+%F"`"
Will print YYYY-MM-DD
Try this code for a simple human readable timestamp:
dt=$(date)
echo $dt
Output:
Tue May 3 08:48:47 IST 2022

KornShell script to get files between two dates

Need to get the files between two given dates via a KornShell (ksh) script. If there are multiple files on one day get the latest of the files for that day.
I haven't tried it out, but there's a mailing list post about finding files between two dates. The relevant part:
Touch 2 files, start_date and
stop_date, like this: $ touch -t
200603290000.00 start_date $ touch -t 200603290030.00 stop_date
Ok, start_date is 03/29/06 midnight,
stop_date is 03/29/06 30 minutes after
midnight. You might want to do a ls
-al to check.
On to find, you can find -newer and
then ! -newer, like this: $ find /dir
-newer start_date ! -newer stop_date -print
Combine that with ls -l, you get: $
find /dir -newer start_date ! -newer
stop_date -print0 | xargs -0 ls -l
(Or you can try -exec to execute ls
-l. I am not sure of the format, so you have to muck around a little bit)
in bash shell, just an example, you can use the -nt test operator (korn shell comes with it also, if i am not wrong).
printf "Enter start date( YYYYMMDD ):"
read startdate
printf "Enter end date( YYYYMMDD ):"
read enddate
touch -t "${startdate}0000.00" sdummy
touch -t "${enddate}0000.00" edummy
for fi in *
do
if [ $fi -nt "sdummy" -a ! $fi -nt "edummy" ] ;then
echo "-->" $fi
fi
done
In a nut shell for ksh :
!/usr/bin/ksh
# main from_date to_date path
# date format: YYMMDDhhmmss
ls -l --time-style "+%y%m%d%H%M%S" $3 | awk '{ print $6 " " $7 }' | while read t n
do
if (( t > $1 )) && (( t < $2 )); then
echo $t $n
fi
done

Resources