onur
onur

Reputation: 6365

Parsing date and time format - Bash

I have date and time format like this(yearmonthday):

20141105 11:30:00

I need assignment year, month, day, hour and minute values to variable.

I can do it year, day and hour like this:

year=$(awk '{print $1}' log.log | sed 's/^\(....\).*/\1/')
day=$(awk '{print $1}' log.log | sed 's/^.*\(..\).*/\1/')  
hour=$(awk '{print $2}' log.log | sed 's/^\(..\).*/\1/')  

How can I do this for month and minute?

--

And I need that every line of my log file:

20141105 11:30:00 /bla/text.1
20141105 11:35:00 /bla/text.2
20141105 11:40:00 /bla/text.3
.... 

I'm trying read line by line this log file and do this:

mkdir -p "/bla/backup/$year/$month/$day/$hour/$minute"
mv $file "/bla/backup/$year/$month/$day/$hour/$minute"

Here is my not working code:

#!/bin/bash
LOG=/var/log/LOG

while read line
do

year=${line:0:4}
month=${line:4:2}
day=${line:6:2}
hour=${line:9:2}
minute=${line:12:2}
file=$(awk '{print $3}')

if [ -f "$file" ]; then

printf -v path "%s/%s/%s/%s/%s" $year $month $day $hour $minute
mkdir -p "/bla/backup/$path"
mv $file "/bla/backup/$path"

fi
done < $LOG

Upvotes: 3

Views: 7717

Answers (7)

Leslie Satenstein
Leslie Satenstein

Reputation: 416

I wrote a function that I usually cut and paste into my script files

function getdate()
{
  local a
  a=(`date "+%Y %m %d %H %M %S" | sed -e 's/ / /'`)
  year=${a[0]}
  month=${a[1]}
  day=${a[2]}
  hour=${a[3]}
  minute=${a[4]}
  sec=${a[5]}
}

in the script file, on a line of it's own

getdate

echo "year=$year,month=$month,day=$day,hour=$hour,minute=$minute,second=$sec"

Of course, you can modify what I provided or use answer [6] above. The function takes no arguments.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 246837

You don't need to call out to awk to date at all, use bash's substring operations

d="20141105 11:30:00"
yr=${d:0:4}
mo=${d:4:2}
dy=${d:6:2}
hr=${d:9:2}
mi=${d:12:2}
printf -v dir "/bla/%s/%s/%s/%s/%s/\n" $yr $mo $dy $hr $mi
echo "$dir"
/bla/2014/11/05/11/30/

Or directly, without all the variables.

printf -v dir "/bla/%s/%s/%s/%s/%s/\n" ${d:0:4} ${d:4:2} ${d:6:2} ${d:9:2} ${d:12:2}

Given your log file:

while read -r date time file; do
    d="$date $time"
    printf -v dir "/bla/%s/%s/%s/%s/%s/\n" ${d:0:4} ${d:4:2} ${d:6:2} ${d:9:2} ${d:12:2}
    mkdir -p "$dir"
    mv "$file" "$dir"
done < filename

or, making a big assumption that there are no whitespace or globbing characters in your filenames:

sed -r 's#(....)(..)(..) (..):(..):.. (.*)#mv \6 /blah/\1/\2/\3/\4/\5#' | sh

Upvotes: 4

NeronLeVelu
NeronLeVelu

Reputation: 10039

eval "$( 
   echo '20141105 11:30:00' \
    | sed 'G;s/\(....\)\(..\)\(..\) \(..\):\(..\):\(..\) *\(.\)/Year=\1\7Month=\2\7Day=\3\7Hour=\4\7Min=\5\7Sec=\6/'
    )"

pass via a assignation string to evaluate. You could easily adapt to also check the content by replacing dot per more specific pattern like [0-5][0-9] for min and sec, ...

posix version so --posix on GNU sed

Upvotes: 1

gniourf_gniourf
gniourf_gniourf

Reputation: 46833

Don't repeat yourself.

d='20141105 11:30:00'
IFS=' ' read -r year month day min < <(date -d"$d" '+%Y %d %m %M')

echo "year: $year"
echo "month: $month"
echo "day: $day"
echo "min: $min"

The trick is to ask date to output the fields you want, separated by a character (here a space), to put this character in IFS and ask read to do the splitting for you. Like so, you're only executing date once and only spawn one subshell.

If the date comes from the first line of the file log.log, here's how you can assign it to the variable d:

IFS= read -r d < log.log

Upvotes: 1

Kent
Kent

Reputation: 195079

I guess you are processing the log file, which each line starts with the date string. You may have already written a loop to handle each line, in your loop, you could do:

d="$(awk '{print $1,$2}' <<<"$line")"
year=$(date -d"$d" +%Y)
month=$(date -d"$d" +%m)
day=$(date -d"$d" +%d)
min=$(date -d"$d" +%M)

Upvotes: 1

Jotne
Jotne

Reputation: 41456

You can use only one awk

month=$(awk '{print substr($1,5,2)}' log.log)
year=$(awk '{print substr($1,0,4)}' log.log)
minute=$(awk '{print substr($2,4,2)}' log.log)
etc

Upvotes: 1

Kalanidhi
Kalanidhi

Reputation: 5092

date command also do this work

#!/bin/bash
year=$(date  +'%Y' -d'20141105 11:30:00')
day=$(date  +'%d' -d'20141105 11:30:00')
month=$(date  +'%m' -d'20141105 11:30:00')
minutes=$(date  +'%M' -d'20141105 11:30:00')
echo  "$year---$day---$month---$minutes"

Upvotes: 1

Related Questions