Barcode
Barcode

Reputation: 89

How to compare a field of a file with current timestamp and print the greater and lesser data?

How do I compare current timestamp and a field of a file and print the matched and unmatched data. I have 2 columns in a file (see below)

oac.bat 09:09
klm.txt 9:00

I want to compare the timestamp(2nd column) with current time say suppose(10:00) and print the output as follows.

At 10:00

greater.txt

xyz.txt 10:32
mnp.csv 23:54

Lesser.txt

oac.bat 09:09
klm.txt 9:00

Could anyone help me on this please ?

I used awk $0 > "10:00", which gives me only 2nd column details but I want both the column details and I am taking timestamp from system directly from system with a variable like

d=`date +%H:%M`

Upvotes: 2

Views: 710

Answers (2)

Ruslan Osmanov
Ruslan Osmanov

Reputation: 21492

Pure Bash

The script can be implemented in pure Bash with the help of date command:

# Current Unix timestamp
let cmp_seconds=$(date +%s)

# Read file line by line
while IFS= read -r line; do
  let line_seconds=$(date -d "${line##* }" +%s) || continue

  (( line_seconds <= cmp_seconds )) && \
    outfile=lesser || outfile=greater

  # Append the line to the file chosen above
  printf "%s\n" "$line" >> "${outfile}.txt"
done < file

In this script, ${line##* } removes the longest match of '* ' (any character followed by a space) pattern from the front of $line thus fetching the last column (the time). The time column is supposed to be in one of the following formats: HH:MM, or H:MM. Actually, date's -d option argument

can be in almost any common format. It can contain month names, time zones, ‘am’ and ‘pm’, ‘yesterday’, etc.

We use the flexibility of this option to convert the time (HH:MM, or H:MM) to Unix timestamp.

The let builtin allows arithmetic to be performed on shell variables. If the last let expression fails, or evaluates to zero, let returns 1 (error code), otherwise 0 (success). Thus, if for some reason the time column is in invalid format, the iteration for such line will be skipped with the help of continue.

Perl

Here is a Perl version I have written just for fun. You may use it instead of the Bash version, if you like.

# For current date
#cmp_seconds=$(date +%s)
# For specific hours and minutes
cmp_seconds=$(date -d '10:05' +%s)

perl -e '
my @t = localtime('$cmp_seconds');
my $minutes = $t[2] * 60 + $t[1];
while (<>) {
  / (\d?\d):(\d\d)$/ or next;
  my $fh = ($1 * 60 + $2) > $minutes ? STDOUT : STDERR;
  printf $fh "%s", $_;
}' < file >greater.txt 2>lesser.txt

The script computes the number of minutes in the following way:

HH:MM = HH * 60 + MM minutes

If the number of minutes from the file are greater then the number of minutes for the current time, it prints the next line to the standard output, otherwise to standard error. Finally, the standard output is redirected to greater.txt, and the standard error is redirected to lesser.txt.

I have written this script for demonstration of another approach (algorithm), which can be implemented in different languages, including Bash.

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 203655

With GNU awk you can just use it's builtin time functions:

awk 'BEGIN{now = strftime("%H:%M")} {
    split($NF,t,/:/)
    cur=sprintf("%02d:%02d",t[1],t[2])
    print > ((cur > now ? "greater" : "lesser") ".txt")
}' file

With other awks just set now using -v and date up front, e.g.:

awk -v now="$(date +"%H:%M")" '{
    split($NF,t,/:/)
    cur = sprintf("%02d:%02d",t[1],t[2])
    print > ((cur > now ? "greater" : "lesser") ".txt")
}' file

The above is untested since you didn't provide input/output we could test against.

Upvotes: 1

Related Questions