Sort files based on day of week - linux

I have several files:
Friday.log
Monday.log
Tuesday.log
Saturday.log
Sunday.log
Thursday.log
Tuesday.log
Wednesday.log
I want to put their filename without .log and contents into one file but in order of day of week starting with Monday to Sunday. I have a command that will put them together without .log but not in order:
awk 'FNR==1{sub(/[.][^.]*$/"", FILENAME); print FILENAME} 1' *.log > all.log
That gives me :
Friday
... Friday contents
Monday
... Monday contents
Tuesday
... Tuesday contents
Saturday
... Saturday contents
Any idea?

You can "play" with the %u parameter of date to know the day of the week of any given date:
$ date -d"last Sunday" +%u
7
However, and since this list is pretty much stable, why don't you just hardcode it in an array?
#!/bin/bash
days=('Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday' 'Saturday' 'Sunday')
for day in "${days[#]}"
do
echo "$day"
cat "$day.log"
done > all.log

Perl solution:
perl -le 'for $day qw(Monday Tuesday Wednesday Thursday Friday Saturday Sunday) {print $day; system("cat $day.log")}'

I ended up just doing:
touch Thursday.log && touch Wednesday.log && touch Tuesday.log && touch Monday.log && ls -t | xargs -i awk 'FNR==1{sub(/[.][^.]*$/"", FILENAME); print FILENAME} 1' {} > all.log

Related

Transform an entire column using "date" command

Here is a dummy CSV file with 3 rows. The actual file has 7 million rows.
testdates.csv:
y_m_d
1997-01-01
1985-06-09
1943-07-14
The date tool can usually be formatted as such , to get the 'day' :
date -d "25 JUN 2011" +%A
=> output: Saturday
Query: How to provide an entire column as input for the date +%A transformation?
The resulting output should be appended to the end of the input file.
Intended output:
y_m_d, Day
1997-01-01, Thursday
1985-06-09, Sunday
1943-07-14, Tuesday
To read multiples dates from a file using GNU date, you can use the -f/--file option:
$ date -f testdates.csv '+%F, %A'
1997-01-01, Wednesday
1985-06-09, Sunday
1943-07-14, Wednesday
Since your file has a header row, we have to skip that, for example using process substitution and sed:
date -f <(sed '1d' testdates.csv) '+%F, %A'
To get your desired output, combine like this:
echo 'y_m_d, Day'
date -f <(sed '1d' testdates.csv) '+%F, %A'
or write to a new file:
{
echo 'y_m_d, Day'
date -f <(sed '1d' testdates.csv) '+%F, %A'
} > testdates.csv.tmp
and after inspection, you can rename with
mv testdates.csv.tmp testdates.csv
Hard to beat that date answer.
GNU awk would be OK too:
gawk -v OFS=', ' '
NR == 1 {$2 = "Day"}
NR > 1 {$2 = strftime("%A", mktime(gensub(/-/, " ", "g", $1) " 0 0 0"))}
1
' testdates.csv
y_m_d, Day
1997-01-01, Wednesday
1985-06-09, Sunday
1943-07-14, Wednesday
Or perl:
perl -MTime::Piece -lne '
print "$_, ", $. == 1
? "Day"
: Time::Piece->strptime($_, "%Y-%m-%d")->strftime("%A")
' testdates.csv
#/bin/bash
while read datespec; do
echo $datespec, $(date -d "$datespec" +%A)
done < testdates.csv
Output:
1997-01-01, Wednesday
1985-06-09, Sunday
1943-07-14, Wednesday

Schedule Cron to skip first Saturday of every month

I need a cron to skip the first Saturday of every month. I know we can run on specific days using the below command, but is there a way to skip on a particular day for every month?
//To run on first Monday of every month
0 2 * * 1 [ date '+\%m' == date '+\%m' -d "1 week ago" ] || /path/to/command
Is your command a binary file or just script?
How about the idea to add something like that in the beginning:
[ $(date | awk '{print $1}') == "Sat" ] && exit 1 || { \
# your code here
...
}
Since there seem to be no option in Cron.
I'm going with script for the above need.
**if [ $(date +%d) -le 7 ] && [ $(date +%u) -eq 1 ] ;**
[ $(date +%d) -le 7 ] - Checks if the days fall in first 7 days of month
[ $(date +%u) -eq 6 ] - Checks if day is equal to Saturday
Thanks.
The following works in cron (don't forget to escape the %):
0 2 * * * [[ `date '+\%u'` -ne '6' && `date '+\%d'` -lt '8' ]] || [[ `date '+\%d'` -gt '7' ]] && /path/to/command
The logic is :
If the day is not a Saturday and the day of the month is 1-7, execute the command
If the above is not correct, check if the day of the month is bigger than 7, if so execute
Another way would be to invert the logic :
0 2 * * * [[ ! ( `date '+\%u'` -eq '6' && `date '+\%d'` -lt '8' ) ]] && /path/to/command
The logic is :
If the day is not the first Saturday, execute the command
man 5 crontab
The "sixth" field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or
a "%" character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the cronfile. A "%" character in the command, unless escaped with a backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.

UNIX: How do I output data from 2 files using a loop structure?

Good afternoon everyone, I have a project I am working on, but I am having a bit of trouble with it. I am supposed to create a script that uses a loop structure to output data from 2 data files.
These are the two data files:
data1:
Dave,7348389800
Bob,3131234567
Carol,2483445576
Mary,3134491390
Ted,2484962204
Alice,6165564458
data2:
Bob,tuesday
Carol,friday
Ted,sunday
Alice,wednesday
Dave,thursday
Mary,saturday
This is how it is supposed look when i display it:
Day Name Phone
__________________________________________
MONDAY Nobody
TUESDAY Bob (313) 123-4567
WEDNESDAY Alice (616) 556-4458
THURSDAY Dave (734) 838-9800
FRIDAY Carol (248) 344-5576
SATURDAY Mary (313) 449-1390
SUNDAY Ted (248) 496-2204
This is my current code:
#!/bin/ksh
for day in monday tuesday wednesday thursday friday saturday sunday
do
day=`grep -i day data2 |cut -d "," -f 2 `
name=`cut -d "," -f 1 data1 `
phone=`cut -d "," -f 2 data1`
done
echo $day $name $phone >>output
And this is the output I am getting:
Day Name Phone
==============
tuesday friday sunday wednesday thursday saturday Dave Bob Carol Mary Ted Alice 7348389800 3131234567 2483445576 3134491390 2484962204 6165564458
Any help would be greatly appreciated!
This works, using printf to get neatly formatted columnar output:
format="%-9s %-9s %s\n"
printf "$format" Day Name Phone
printf "$format" Day Name Phone | sed 's/./-/g'
for day in monday tuesday wednesday thursday friday saturday sunday
do
who=$(grep -i "$day" data2 | cut -d "," -f 1)
if [ -z "$who" ]
then
who="NOBODY"
phone=""
else
phone=$(grep -i "$who" data1 | sed 's/^[^,]*,\(...\)\(...\)\(....\)/(\1) \2-\3/')
fi
printf "$format" $(echo "$day" | tr 'a-z' 'A-Z') "$who" "$phone"
done
You could investigate typeset -u uday="$day" and then pass "$uday" to the printf; that doesn't seem to be an option in Bash 3.x, but it works in Korn shell and in Bash 4.x (for big enough values of x). […Thinking about it, the grep | cut and grep | sed sequences could (and probably should) be replaced by pure sed, which is tidier still. You could also avoid the repeated printf to deal with the heading by using sed 'p;s/./-/g'. Fixing those issues is left as an exercise for the reader…]
Output:
Day Name Phone
---------------------------
MONDAY NOBODY
TUESDAY Bob (313) 123-4567
WEDNESDAY Alice (616) 556-4458
THURSDAY Dave (734) 838-9800
FRIDAY Carol (248) 344-5576
SATURDAY Mary (313) 449-1390
SUNDAY Ted (248) 496-2204
awk to the rescue!
$ awk -F, -vOFS="\t" '
BEGIN{split("1monday 2tuesday 3wednesday 4thursday 5friday 6saturday 7sunday",days," ")}
NR==FNR{a[$1]=$2;next} {b[$2]=$1}
END{for(i in days) {
d=substr(days[i],2,length(days[i])-1);
dp=toupper(days[i]);
if(b[d])
print dp,b[d],a[b[d]];
else
print dp,"Nobody"}}' data1 data2
| sort | cut -c2- | column -t
| sed -r 's/([0-9]{3})([0-9]{3})([0-9]{4}$)/(\1) \2-\3/'
MONDAY Nobody
TUESDAY Bob (313) 123-4567
WEDNESDAY Alice (616) 556-4458
THURSDAY Dave (734) 838-9800
FRIDAY Carol (248) 344-5576
SATURDAY Mary (313) 449-1390
SUNDAY Ted (248) 496-2204

Configuring date command to meet my format

I have a date in YYYY.MM.DD HH:SS format (e.g. 2014.02.14 13:30). I'd like to convert it in seconds since epoch using the date command.
The command
date -d"2014.02.14 13:30" +%s
won't work, because of the dots separation.
Any Ideas?
Why don't you make the date format acceptable? Just replace dots with dashes:
$ date --date="`echo '2014.02.14 13:30' | sed 's/\./-/g'`" +%s
1392370200
Here I first change the format:
$ echo '2014.02.14 13:30' | sed 's/\./-/g'
2014-02-14 13:30
and then use the result as a parameter for date.
Note that the result depends on your timezone.
You can use:
s='2014.02.14 13:30'
date -d "${s//./}"
Fri Feb 14 13:30:00 EST 2014
To get EPOCH value:
date -d "${s//./}" '+%s'
1392402600
using awk :
s=`echo "2014.02.14 13:30" | awk '{gsub(/\./,"-",$0);print $0}'`
echo -d "$s"
date -d "$s" +%s
output:
Fri Feb 14 13:30:00 IST 2014
1392364800
Perl: does not require you to munge the string
d="2014.02.14 13:30"
epoch_time=$(perl -MTime::Piece -E 'say Time::Piece->strptime(shift, "%Y.%m.%d %H:%M")->epoch' "$d")
echo $epoch_time
1392384600
Timezone: Canada/Eastern
I Finally solved it using
awk 'BEGIN{FS=","}{ gsub(/./," ",$1);gsub(/:/," ",$2); var=sprintf("%s %s 00",$1,$2); print mktime(var), $3,$4,$5,$6,$7 }' myfile | less
so myfile:
2014.09.24,15:15,1.27921,1.27933,1.279,1.27924,234
became
1411582500 1.27921 1.27933 1.279 1.27924 234
:)

Cron Expression for ignoring 1st Saturday of the year & run on all the Saturdays of the year

Can someone help me in building the cron expression. I've a requirement where I need to run my Job on all the Saturdays at 9:00 AM in a year excluding 1st Saturday of the year.
I had tried with the below expression, but its not working..
0 0 9 ? 1 7#2,7#3,7#4 *, 0 0 9 ? 2-12 SAT *
0 0 9 ? 1 7#2,7#3,7#4 * - It means In the month of January run my job at 9:00 AM on 2nd,3rd,4th Saturdays. But the problem here is it is taking the Last saturday only (i.e. 7#4). In some tutorials I read that comma means it considers all the values but to my surprise it is considering only the last value)
0 0 9 ? 2-12 SAT * - It means from the month of February till December I need to run my job at 9:00 AM.
I need to combine these 2 expressions in such a way it should satisfy my requirement.
Thanks In Advance
You need put compare in your program, not in cronjob. For example, in Unix shell script:
#!/usr/bin/env bash
date=$(date +%a)
month=$(date +%m)
day=$($date +%e)
if [ "$date" = "Sat" -a "$month" = "Jan" -a "$day" -lt 8 ];then
echo "Doesn't run this script at 1st Saturday of the year."
exit
fi
# put rest script
set the cronjob to run it only at 9am on Saturday
0 9 * * 6 YOUR_PROGRAM
Explanation:
%a locale's abbreviated weekday name (e.g., Sun)
%b locale's abbreviated month name (e.g., Jan)
%e day of month, space padded; same as %_d

Resources