1. Overview

Getting the current date in an awk script has many practical use cases, such as date-time logging, data analysis, data filtering, etc. However, awk doesn’t have good built-in support for date manipulations, and we often need to rely upon external commands from within an awk script.

In this tutorial, we’ll explore multiple approaches to get the current date in awk.

2. Understanding the Scenario

Let’s take a look at the sample events.txt file that contains a list of events along with their date of occurrence:

$ cat events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3
2028-10-24 event4
2023-12-12 event5
2035-12-25 event6

Our goal is to use an awk script to filter the events and show only those that happened in the past.

Usually, when working in Shell, we can use the date command to get the current date:

$ date +%Y-%m-%d
2023-10-25

However, to solve our use case, we’ll need the current date within our script to compare the date of occurrence of different events with the current date.

Lastly, let’s see the expected output of our awk script:

2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

In the following sections, we’ll reuse the events.txt file to learn various approaches for solving our use case.

3. Passing as a Parameter

First, let’s see how we can use the -v flag to pass the current date as the current_date parameter to awk:

$ awk -v current_date="$(date +%Y-%m-%d)" 
'BEGIN {
    print current_date;
}'
2023-10-24

We used the command substitution to set the value of current_date beforehand.

Now, let’s write the filter_events_v1.awk script that assumes we’re setting the current_date parameter during execution:

$ cat filter_events_v1.awk
{
    if ($0 <= current_date) {
        print $0;
    }
}

Since the dates are in the “%Y-%m-%d” format, we did a lexicographic string comparison to show only those events before the current date.

Lastly, let’s see our script in action:

$ awk -v current_date="$(date +%Y-%m-%d)" -f filter_events_v1.awk events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

Great! It looks like we got this one right.

4. Passing From Pipe

We can also pass the current date to an awk script from a pipe:

$ date +%Y-%m-%d | awk '{print $0}' -
2023-10-24

We used the (stdin) filename argument to read from standard input.

Further, let’s write the filter_events_v2.awk script that takes multiple file arguments, with stdin being the first one:

$ cat filter_events_v2.awk
{
    if (NR==1) {
        current_date=$0
    } else if ($0 < current_date) {
        print $0
    }
}

We set current_date only for the first line of input. Otherwise, we use it for comparison.

Lastly, let’s verify our script by passing two file arguments, namely, (stdin) and events.txt:

$ date +%Y-%m-%d | awk -f filter_events_v2.awk - events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

It works as expected.

5. Passing Using Process Substitution

Alternatively, we can use process substitution to pass the current date:

$ awk '{
    print $0;
}' <(date +%Y-%m-%d)
2023-10-24

For awk, data passed through process substitution is similar to data received from any other file. So, we can reuse the filter_events_v2.awk without any change.

Like earlier, let’s confirm that the script is working fine for this approach, too:

$ awk -f filter_events_v2.awk <(date +%Y-%m-%d) events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

It works fine. Moreover, we should note that we passed two file arguments, wherein the first one is via process substitution.

6. Using strftime() Function

awk doesn’t offer advanced capabilities around date operations. However, it has built-in support for formatting the dates using the stftime() function because it’s closely related to text operations.

Let’s take a look at the default behavior of the strftime() function when we only pass a format string without any timestamps:

$ awk 'BEGIN {
    current_date=strftime("%Y-%m-%d"); 
    print current_date;
}'
2023-10-24

We can see that strftime() operates on the current timestamp by default and formats it using the format string passed to it.

So, let’s solve our use case by writing the filter_events_v3.awk using the strftime() function’s default behavior:

$ cat filter_events_v3.awk
BEGIN {
     current_date=strftime("%Y-%m-%d");
}
{
    if ($0 < current_date) {
        print $0
    }
}

Lastly, let’s run and validate our script:

$ awk -f filter_events_v3.awk events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

7. Using system() Function

awk doesn’t have built-in support for date operations, but we can use the system() function to call external commands like date.

Let’s see how we can run the date command to get the current date using this approach:

$ awk '
BEGIN {
    system("date +%Y-%m-%d")
}'
2023-10-24

We can see the current date shown as the output. We must capture this value in a variable for later use for our use case.

For this purpose, we can write the output from the date command to a file and read the content into a variable. It’s a bit unintuitive, so let’s look at our new script, filter_events_v4.awk:

$ cat filter_events_v4.awk
BEGIN {
    system("date +%Y-%m-%d > current_date.txt")
}
{
    if (NR == 1) {
        current_date=$0
    }
    if ($0 < current_date) {
        print $0
    }
}

Our script reads input from two files, namely, current_date.txt and events.txt. After reading the first record (NR=1), it sets the current_date variable as the current date. Later, we use it for comparison against the date of occurrences of the events.

Finally, let’s see our script in action:

$ awk -f filter_events_v4.awk current_date.txt events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

Fantastic! It looks like we nailed this one.

8. Using getline() Function

We can use the getline() function to read content from an input file or a command. Let’s solve our use case using the getline() function in this section.

8.1. Into a Variable From Pipe

First, let’s see how we can get the current date into a variable using the getline() function:

$ awk '
BEGIN {
    "date +%Y-%m-%d" | getline current_date; 
    close(current_date)
    print current_date
}'
2023-10-24

We passed the command string to the getline() function from a pipe. Further, the getline() function takes the output after the execution of the command and stores it in the current_date command variable.

Additionally, as a best practice, it’s important to remember that we must close the command when using it with a pipe. So, we closed the current_date command variable.

Now, let’s write the filter_events_v5.awk script that reads the current date into the current_date variable using the getline() function:

$ cat filter_events_v5.awk

BEGIN {
    "date +%Y-%m-%d" | getline current_date;
    close(current_date)
}
{
    if ($0 < current_date) {
        print $0
    }
}

Finally, let’s verify our script by running it:

$ awk -f filter_events_v5.awk events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

It works as expected.

8.2. Into a Variable From File

Alternatively, we can read the current date from a file using the getline() function. Let’s use process substitution to mimic this scenario where awk treats the output from the command as if coming from an input file:

$ awk '
BEGIN {
    getline current_date;
    print current_date;
}' <(date +%Y-%m-%d)
2023-10-24

Now, let’s write the filter_events_v6.awk script to solve our use case using this approach:

$ cat filter_events_v6.awk
BEGIN {
    getline current_date;
}
{
    if ($0 < current_date) {
        print $0
    }
}

We got the current date value in the current_date variable. So, we could use it for comparison in the main block.

Lastly, we can run our script with two file arguments, the first one being the process substitution and events.txt as the second file:

$ awk -f filter_events_v6.awk <(date +%Y-%m-%d) events.txt
2022-10-24 event1
1993-06-09 event2
2003-07-13 event3

Great! Our approach looks correct.

9. Conclusion

In this article, we learned how to get the current date in awk and used it for a data filtering use case. Further, we learned how to pass the current date as a parameter or from a pipe to our awk script.

Lastly, we explored the system(), strftime(), and getline() functions while solving the use case.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.