How to calculate last business day of the month in Korn Shell? - date

I've seen this question answered in other languages but not the Korn Shell. I need to prevent a script from being run on the last business day of the month (we can assume M-F are business days, ignore holidays).

This function works in Bash, Korn shell and zsh, but it requires a date command (such as GNU date) that has the -d option:
function lbdm { typeset lbdm ldm dwn m y; (( m = $1 + 1 )); if [[ $m = 13 ]]; then m=1; (( y = $2 + 1 )); else y=$2; fi; ldm=$(date -d "$m/1/$y -1 day"); dwn=$(date -d "$ldm" +%u);if [[ $dwn = 6 || $dwn = 7 ]]; then ((offset = 5 - $dwn)); lbdm=$(date -d "$ldm $offset day"); else lbdm=$ldm; fi; echo $lbdm; }
Run it like this:
$ lbdm 10 2009
Fri Oct 30 00:00:00 CDT 2009
Here is a demo script broken into separate lines and with better variable names and some comments:
for Month in {1..12} # demo a whole year
do
Year=2009
LastBusinessDay=""
(( Month = $Month + 1 )) # use the beginning of the next month to find the end of the one we're interested in
if [[ $Month = 13 ]]
then
Month=1
(( Year++ ))
fi;
# these two calls to date could be combined and then parsed out
# this first call is in "American" order, but could be changed - everything else is localized - I think
LastDayofMonth=$(date -d "$Month/1/$Year -1 day") # get the day before the first of the month
DayofWeek=$(date -d "$LastDayofMonth" +%u) # the math is easier than Sun=0 (%w)
if [[ $DayofWeek = 6 || $DayofWeek = 7 ]] # if it's Sat or Sun
then
(( Offset = 5 - $DayofWeek )) # then make it Fri
LastBusinessDay=$(date -d "$LastDayofMonth $Offset day")
else
LastBusinessDay=$LastDayofMonth
fi
echo "$LastDayofMonth - $DayofWeek - $LastBusinessDay"
done
Output:
Sat Jan 31 00:00:00 CST 2009 - 6 - Fri Jan 30 00:00:00 CST 2009
Sat Feb 28 00:00:00 CST 2009 - 6 - Fri Feb 27 00:00:00 CST 2009
Tue Mar 31 00:00:00 CDT 2009 - 2 - Tue Mar 31 00:00:00 CDT 2009
Thu Apr 30 00:00:00 CDT 2009 - 4 - Thu Apr 30 00:00:00 CDT 2009
Sun May 31 00:00:00 CDT 2009 - 7 - Fri May 29 00:00:00 CDT 2009
Tue Jun 30 00:00:00 CDT 2009 - 2 - Tue Jun 30 00:00:00 CDT 2009
Fri Jul 31 00:00:00 CDT 2009 - 5 - Fri Jul 31 00:00:00 CDT 2009
Mon Aug 31 00:00:00 CDT 2009 - 1 - Mon Aug 31 00:00:00 CDT 2009
Wed Sep 30 00:00:00 CDT 2009 - 3 - Wed Sep 30 00:00:00 CDT 2009
Sat Oct 31 00:00:00 CDT 2009 - 6 - Fri Oct 30 00:00:00 CDT 2009
Mon Nov 30 00:00:00 CST 2009 - 1 - Mon Nov 30 00:00:00 CST 2009
Thu Dec 31 00:00:00 CST 2009 - 4 - Thu Dec 31 00:00:00 CST 2009
Note: I discovered during testing that if you try to use this for dates around World War II that it fails due to wartime time zones like CWT and CPT.
Edit: Here's a version that should run on AIX and other systems that can't use the above. It should work on Bourne, Bash, Korn and zsh.
function lbdN { cal $1 $2 | awk 'NF == 0 {next} FNR > 2 {week = $0} END {num = split(week, days); lbdN = days[num]; if ( num == 1 ) { lbdN -= 2 }; if ( num == 7 ) { lbdN-- }; print lbdN }'; }
You may have to make adjustments if your cal starts weeks on Monday.
Here's how you can use it:
month=12; year=2009 # if these are unset or null, the current month/year will be used
if [[ $(date +%d) == $(lbdN $month $year) ]];
then
echo "Don't do stuff today"
else
echo "It's not the last business day of the month"
fi
making appropriate adjustments for your shell's if...then syntax, of course.
Edit: Bug Fix: The previous version of lbdN failed when February ends on Saturday the 28th because of the way it used tail. The new version fixes that. It uses only cal and awk.
Edit: For completeness, I thought it would be handy to include functions for the first business day of the month.
Requires date with -d:
function fbdm { typeset dwn d; dwn=$(date -d "$1/1/$2" +%u); d=1; if [[ $dwn = 6 || $dwn = 7 ]]; then (( d = 9 - $dwn )); fi; echo $(date -d "$1/$d/$2"); }
For May 2010:
Mon May 3 00:00:00 CDT 2010
Requires cal and awk only:
function fbdN { cal $1 $2 | awk 'FNR == 3 { week = $0 } END { num = split(week, days); fbdN = days[1]; if ( num == 1 ) { fbdN += 2 }; if ( num == 7 ) { fbdN++ }; print fbdN }'; }
For August 2010:
2

Related

How to rearrange dates of the month when they span across end of current month to beginning of next month

I have to work on data which goes according to dates of the month. When I extract the dates from the filename I get a random arrangement of the dates, as below.
31 02 28 30 27 01 29 03 04
This is processing the data from 27th August to 4th September. I need the dates arranged sequentially from 27th to 4th. I have to process 9 dates at a time. This problem arises at the end of the month when I have this month's dates (large figures) and next month (small figures).So I sort the array which I call #fdaylist. I get
01 02 03 04 27 28 29 30 31.
To get what I want the script snippet below, does the job and gives
27 28 29 30 31 01 02 03 04
I am sure if this script can work all the time. It reproduces the sequence several time over, so I have to use the uniq() function.
I will appreciate if I can get a suggestion of a better way of achieving my objective.
my $last_occ=lastidx { /0\d/ } #fdaylist;
if($last_occ > 1){
foreach(#fdaylist){
for(my $mm=$last_occ+1; $mm < #fdaylist; ++$mm){
push (#fday, $fdaylist[$mm]);
}
for(my $nn=0; $nn <= $last_occ; ++$nn){
push (#fday, $fdaylist[$nn]);
}
}
}
#fday = uniq(#fday);
I assume that the numbers must be consecutive, with one gap, otherwise it wouldn't be possible to decide which way some belong. I also assume that there always is a gap.† (Nope. While dates are indeed consecutive, they may straddle two months or lie within one, as clarified.)
One way: Go through the sorted array moving items from front to back until reaching a gap
use warnings;
use strict;
use feature 'say';
# Dates are consecutive, either straddling two months or within a month
my #dates = (31, 02, 28, 30, 27, 01, 29, 03, 04); # or can be 05..13 etc
#dates = sort { $a <=> $b } #dates;
if (consec_nums(\#dates)) {
say "Consecutive numbers (dates in same month), nothing to do (#dates)";
}
else {
my $last_moved;
while (1) {
push #dates, $last_moved = shift #dates;
last if $dates[0] > $last_moved+1;
}
#dates = map { sprintf "%02d", $_ } #dates; # for 01 02 etc
}
say "#dates";
# Returns true (1) if numbers are consecutive, like consecutive dates
# in a single month, false (undef) otherwise. Assumes a sorted array
sub consec_nums {
my ($ra) = #_;
my $prev = $ra->[0];
for my $i (1..$#$ra) {
return if $ra->[$i] > $prev+1;
$prev = $ra->[$i];
}
return 1;
}
Another way: Go over the sorted array to find the last index before the gap (after which numbers stop being consecutive); then splice-and-push
# same sorted #dates, same assumptions. same consec_nums() sub
if (consec_nums(\#dates)) {
say "Consecutive numbers (dates in same month), nothing to do (#dates)";
}
else {
my $consec_idx;
for my $i (0 .. $#dates) {
$consec_idx = $i, last
if $dates[$i]+1 < $dates[$i+1];
}
push #dates, splice #dates, 0, $consec_idx+1;
}
say "#dates";
† For the mentioned assumptions:
If we could have 1 2 10 30 31 then should that be 10 30 31 1 2 or 30 31 1 2 10?
If there were no gap (all dates in one month), like 05 .. 13, then the procedures above would break. If such a case is possible then first test for it.
It has been clarified in a comment that this is indeed possible, that all dates are inside one month. The answer above has then been amended with the test for such a case.
Please see if the following sample code performs operation you described in your post.
The code:
reads dates into a string
splits the sting and sorts dates into an array
find index of last day starting with 0\d
re-arranges the array with two array slices
Note: print out spits input, ordered and re-ordered data
use strict;
use warnings;
use feature 'say';
while( <DATA> ) {
chomp;
say 'GOT: ' . $_;
my #dates = sort split ' ', $_;
say 'IN: ' . join(' ',#dates);
my $index = -1;
/0\d/ && $index++ for #dates;
#dates = (#dates[$index+1..$#dates],#dates[0..$index]);
say 'OUT: ' . join(' ', #dates);
say '-' x 45;
}
__DATA__
31 02 28 30 27 01 29 03 04
28 03 26 02 25 01 23 22 24
Output
GOT: 31 02 28 30 27 01 29 03 04
IN: 01 02 03 04 27 28 29 30 31
OUT: 27 28 29 30 31 01 02 03 04
---------------------------------------------
GOT: 28 03 26 02 25 01 23 22 24
IN: 01 02 03 22 23 24 25 26 28
OUT: 22 23 24 25 26 28 01 02 03
---------------------------------------------

Google App Script formatted date Match in Array without iterating

I am trying to find the first occurrence of a date, happens to be in 'MMM dd" format, within a coloumn, by using findIndex method.
The following code isnt able to achieve it
function copyInvoiceDetailsToDB() {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ss = sss.getSheetByName('Import MT Order Sheet'); //Source Sheet
var compareDate = ss.getRange(1,4).getValue(); // Search item
///var mmm = Utilities.formatDate(compareDate,"IST", 'MMM dd');
var reldata = ss.getRange('A3:AA'+ a).getValues();
var tss = SpreadsheetApp.openById("1xhPD6tlJiU33_tdnC82p-
e9rWA8mmMtI0g9jDLkk6s0"); // sheet being searched
var ss = tss.getSheetByName('DB');
var ssdata = ss.getRange('A:A').getValues(); // Range containing the values
var a = ssdata.indexOf(compareDate);
Logger.log(a);
Logger.log(compareDate);
Logger.log(ssdata);
return;
Generates the following log.
Please help me understand where I must be going wrong.
[17-11-22 02:40:11:568 IST] -1.0
[17-11-22 02:40:11:569 IST] Nov 22
[17-11-22 02:40:11:572 IST] [[], [Sun Nov 19 00:00:00 GMT+05:30 2017], [Mon Nov 20 00:00:00 GMT+05:30 2017], [Mon Nov 20 00:00:00 GMT+05:30 2017], [Mon Nov 20 00:00:00 GMT+05:30 2017], [Tue Nov 21 00:00:00 GMT+05:30 2017], [Tue Nov 21 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00 GMT+05:30 2017], [Wed Nov 22 00:00:00
How about this answer? From your question, I understood as follows.
You want to retrieve the first occurrence (the row number?) of a date using a string 'MMM dd".
You want to understand for retrieving values using indexOf().
About retrieving values from array using indexOf()
When you want to retrieve a value from an array using indexOf(), the array has to be 1 dimensional array. This is pointed out by Sandy Good.
When a value is retrieved from an 1 dimensional array using indexOf(), it doesn't retrieve the value included in each element, it retrieves the same value for each element.
["foo", "bar", "baz"].indexOf("ba") is -1.
This means that there is no "ba" in each element in the array.
["foo", "bar", "baz"].indexOf("bar") is 1.
This means that there is "bar" at index 1 of the array.
When it retrieves the value included in each element, each element has to be used as a string.
["foo", "bar", "baz"].indexOf("ba") is -1.
"bar".indexOf("ba") is 0.
This means that the string of "ba" is found at 1st string in "bar". So in the case of "bbbar".indexOf("ba"), the result is 2.
The modification point reflected them is as follows.
Modification point :
From :
var a = ssdata.indexOf(compareDate);
Logger.log(a);
To :
var a;
for (var i in ssdata) {
if (ssdata[i][0].indexOf(compareDate) > -1) {
a = i;
break;
}
}
Logger.log(a);
a is the index with the value included "Nov 22" in the array of ssdata. If you want to the row number, please add 1 to it.
When your result shown at the log is used, a is 7.
References :
Array.prototype.indexOf()
String.prototype.indexOf()
If I misunderstand your question, I'm sorry.

Perl touch -t file error for a future date

I am trying to touch a file(for referencing date) with a future date something like -
Current date - $date
Fri Jan 6 03:59:55 EST 2017
touch -t 201702032359.59 /var/tmp/ME_FILE_END
on checking the timestamp of the file as -
$ ls -lrt /var/tmp/ME_FILE_END
getting an output with only date and not the entire timestamp(hhmm.sec)
-rw-r--r-- 1 abcproc abc 0 Feb 3 2017 /var/tmp/ME_FILE_END
But for a date with is less than or equal to current it gives correct result -
touch -t 201612010000.00 /var/tmp/ME_FILE_START
ls -lrt /var/tmp/ME_FILE_START
-rw-r--r-- 1 abcproc abc 0 Dec 1 00:00 /var/tmp/ME_FILE_START
Can someone please suggest why this discrepancy ?
It's just the way ls displays the date. When far from now, the modification time is not displayed.
If you want details regarding the last access / modification / change time, you should be using stat.
stat /var/tmp/ME_FILE_END
You will see the expected output.
For example:
[10:29:41]dabi#gaia:~$ touch -t 201702032359.59 /var/tmp/ME_FILE_END
[10:29:43]dabi#gaia:~$ ls -ltr /var/tmp/ME_FILE_END
-rw-rw-r-- 1 dabi dabi 0 feb. 3 2017 /var/tmp/ME_FILE_END
[10:29:47]dabi#gaia:~$ stat /var/tmp/ME_FILE_END
File : '/var/tmp/ME_FILE_END'
Size : 0 Blocks : 0 I/O blocks : 4096 empty file
Device : 803h/2051d Inode : 5374373 Links : 1
Access : (0664/-rw-rw-r--) UID : ( 1000/ dabi) GID : ( 1000/ dabi)
Access : 2017-02-03 23:59:59.000000000 +0100
Change : 2017-02-03 23:59:59.000000000 +0100
Change : 2017-01-06 10:29:43.364630503 +0100
Birth : -

Sort with Text Months

Not sure the best way to accomplish this.
I get these results to a text file from a mysql query. I would like to the sort 4th column with the oldest entry first.
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Wed Apr 3 17:00:52 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 14:01:05 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Fri Apr 5 13:00:56 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 08:00:59 2013 Mon Apr 8 08:00:59 2013 10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 09:00:55 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 07:00:53 2013
sort -r -k10 test does not seem to cut it.
A Perl solution using Time::Piece (in the Perl standard library since 5.10.0) and a Schwartzian Transform.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;
say map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [ $_, sortdate($_) ] } <DATA>;
sub sortdate {
my $date = join ' ', (split)[2 .. 6];
return Time::Piece->strptime($date, '%a %b %d %H:%M:%S %Y')->datetime;
}
__END__
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Wed Apr 3 17:00:52 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 14:01:05 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Fri Apr 5 13:00:56 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 08:00:59 2013 Mon Apr 8 08:00:59 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 09:00:55 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 07:00:53 2013
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
FOR /f "tokens=1-7*" %%a IN (sqlout.txt) DO (
SET "month="
FOR %%m IN (01 Jan 02 Feb 03 Mar 04 Apr 11 Nov 12 Dec) DO IF NOT DEFINED month (
IF %%d==%%m SET month=!prev!
SET prev=%%m
)
SET /a day=100+%%e
ECHO(%%g!month!!day!%%f*%%a %%b %%c %%d %%e %%f %%g %%h
)
)>tempfile.1
(
FOR /f "delims=" %%i IN ('sort tempfile.1') DO (
SET line=%%i
ECHO(!line:**=!
)
) >sortedoutput.txt
DEL tempfile.1 /F /Q
On the sample data, there are 8 significant columns. Of these, the fourth is month, fifth date, sixth time and seventh year. I have no idea what you mean by the "fourth" column being "the" date since there are two separate dates in each line.
The process simply picks up the fourth column and looks through a list of month numbers (2-digit) and month abbreviations. It's easier to save the previous element for use when the next is compared, so when the monthname matches the fourth column in %%d, the month variable is set, and that will turn off any further processing of the month.
You may have noticed I've not listed all of the months This gives you something to do. It obviously won't work unless all of the months are entered in the list.
Next we deal with the fifth column, and add 100 to the day number, producing a number from 101 to 131. These numbers all have three characters.
Next we ECHO out a string of
the year from column 7 in %%g
the 2-character month number in month
the 3-digit augmented day number
the time from column 6
an asterisk
each of the elements of the original line
Next step is to read each of those lines after sorting.
set the sorted line into line
echo everything from line except the part up to the first asterisk.

Shorten a sed command - using it to make asterisk call logs

I know that asterisk creates it's own call logs in the form of a csv file. For my purposes I need the call logs formatted as I have depicted below. I use:
ls -l /var/spool/asterisk/monitor as the basis for my call logs, which produces this:
-rw------- 1 asterisk asterisk 112684 2013-02-07 17:24 20130207-172424-+15551235566-IN.wav
-rw------- 1 asterisk asterisk 44 2013-02-07 17:53 20130207-175311-+15554561122-IN.wav
-rw------- 1 asterisk asterisk 2019564 2013-02-07 18:00 20130207-175828-15554561122-OUT.wav
-rw------- 1 asterisk asterisk 44 2013-02-07 22:09 20130207-220805-15554561122-OUT.wav
-rw------- 1 asterisk asterisk 44 2013-02-07 22:12 20130207-221204-15551235566-OUT.wav
-rw------- 1 asterisk asterisk 111084 2013-02-07 22:13 20130207-221255-15551235566-OUT.wav
-rw------- 1 asterisk asterisk 364844 2013-02-07 22:39 20130207-223843-15558271212-OUT.wav
-rw------- 1 asterisk asterisk 4279404 2013-02-07 23:53 20130207-234836-5552785454-OUT.wav
-rw------- 1 asterisk asterisk 44 2013-02-08 00:00 20130208-000026-+15559813232-IN.wav
The part I need help with is my command below. It works and produces the exact results I want; however, it seems bulky to me. Can it be shortened?
variables
YESTER=$(date -d "-24 hours" +"%Y-%m-%d-%H%M")
TODAY=$(date +"%Y-%m-%d-%H%M_UTC")
create call log (command I'd like to change)
ls -l /var/spool/asterisk/monitor/ |grep '\.wav'|awk '{print $8 " " $5/1000000}'|sed -e 's/4\.4e\-05/NOT RECORDED/g' -e 's/\.wav//g' -e 's/-/ /g' -e 's/OUT/OUT - Approx Minutes:/g' -e 's/IN/IN - Approx Minutes:/g' -e 's/\(\.[0-9]\).*$/\1/g' -e 's/^.\{15\}/& UTC -/' -e 's/^.\{13\}/&:/' -e 's/^.\{11\}/&:/' -e 's/^.\{6\}/&-/' -e 's/^.\{4\}/& /' -e 's/+//g' > /var/spool/asterisk/monitor/call_logs/${YESTER}__${TODAY}-call-log.txt
For readability here is the command separated by line (without | ):
ls -l /var/spool/asterisk/monitor/
grep '\.wav'
awk '{print $8 " " $5/1000000}'
sed -e 's/4\.4e\-05/NOT RECORDED/g'
-e 's/\.wav//g'
-e 's/-/ /g'
-e 's/OUT/OUT - Approx Minutes:/g'
-e 's/IN/IN - Approx Minutes:/g'
-e 's/\(\.[0-9]\).*$/\1/g'
-e 's/^.\{15\}/& UTC -/'
-e 's/^.\{13\}/&:/'
-e 's/^.\{11\}/&:/'
-e 's/^.\{6\}/&-/'
-e 's/^.\{4\}/& /'
-e 's/+//g'
> /var/spool/asterisk/monitor/call_logs/${YESTER}__${TODAY}-call-log.txt
Output:
2013 02-07 17:24:24 UTC - 15551235566 IN - Approx Minutes: 0.1
2013 02-07 17:53:11 UTC - 15554561122 IN - Approx Minutes: NOT RECORDED
2013 02-07 17:58:28 UTC - 15554561122 OUT - Approx Minutes: 2.0
2013 02-07 22:08:05 UTC - 15554561122 OUT - Approx Minutes: NOT RECORDED
2013 02-07 22:12:04 UTC - 15551235566 OUT - Approx Minutes: NOT RECORDED
2013 02-07 22:12:55 UTC - 15551235566 OUT - Approx Minutes: 0.1
2013 02-07 22:38:43 UTC - 15558271212 OUT - Approx Minutes: 0.3
2013 02-07 23:48:36 UTC - 5552785454 OUT - Approx Minutes: 4.2
2013 02-08 00:00:26 UTC - 15559813232 IN - Approx Minutes: NOT RECORDED
You can put all formating into AWK, why you use sed?
To got it simple, use
[root#gleb monitor]# ls -l --time-style="+%Y-%m-%d %H:%M -"
-rw-r--r-- 1 asterisk asterisk 5195 2013-01-09 21:42 - 20130109-214242-1357756962.1658.WAV
-rw-r--r-- 1 asterisk asterisk 13450 2013-01-13 22:33 - 20130113-223350-1358105630.4124.WAV
Unfortanly i can't give full script, becuase i have other files. Based on such ls command output you now not need rewrite data, so can use it as column.
You can do full features processing including formating in single awk expression.
http://www.gnu.org/software/gawk/manual/html_node/Printf-Examples.html
$ cat tst.awk
{
mins = $5 / 1000000
mins = ( mins == "4.4e-05" ? "NOT RECORDED" : sprintf("%.1f",mins) )
split($8,fname,/-\+?|\./)
date = fname[1]
time = fname[2]
nrs = fname[3]
dir = fname[4]
printf "%s %s-%s ",substr(date,1,4),substr(date,5,2),substr(date,7,2)
printf "%s:%s:%s UTC - ",substr(time,1,2),substr(time,3,2),substr(time,5,2)
printf "%s %s - Approx Minutes: %s\n",nrs,dir,mins
}
$ awk -f tst.awk file
2013 02-07 17:24:24 UTC - 15551235566 IN - Approx Minutes: 0.1
2013 02-07 17:53:11 UTC - 15554561122 IN - Approx Minutes: NOT RECORDED
2013 02-07 17:58:28 UTC - 15554561122 OUT - Approx Minutes: 2.0
2013 02-07 22:08:05 UTC - 15554561122 OUT - Approx Minutes: NOT RECORDED
2013 02-07 22:12:04 UTC - 15551235566 OUT - Approx Minutes: NOT RECORDED
2013 02-07 22:12:55 UTC - 15551235566 OUT - Approx Minutes: 0.1
2013 02-07 22:38:43 UTC - 15558271212 OUT - Approx Minutes: 0.4
2013 02-07 23:48:36 UTC - 5552785454 OUT - Approx Minutes: 4.3
2013 02-08 00:00:26 UTC - 15559813232 IN - Approx Minutes: NOT RECORDED
So just do:
ls -l /var/spool/asterisk/monitor/*.wav | awk -f tst.awk
Although feasible in your case, you should generally avoid parsing ls. I would prefer to see a solution using find instead. If you have access to GNU awk, then you can simplify your pipeline considerably. Run like:
awk -f script.awk <(find /var/spool/asterisk/monitor/ -maxdepth 1 -type f -name "*.wav" -printf "%p %s\n" | sort -n)
Contents of script.awk:
BEGIN {
t = systime()
y = t - 60 * 60 * 24
t = strftime("%Y-%m-%d-%H%M_UTC", t)
y = strftime("%Y-%m-%d-%H%M", y)
}
{
p = "^..(....)(..)(..)-(..)(..)(..)-\\+?([^-]*)-([^\\.]*).*$"
r = "\\1 \\2-\\3 \\4:\\5:\\6 UTC - \\7 \\8 - Approx Minutes:"
s = ($2 != 44 ? sprintf("%.1f", $2/1000000) : "NOT RECORDED")
print gensub(p, r, "", $1) FS s > y "__" t "-call-log.txt"
}
In my testing, this generates a single log file containing your desired output. Because you are now using find, the method could be easily modified if your filesnames were to begin containing whitespace or newline characters. Please let me know how it goes. Cheers.