3

I have a large number of files in a log-directory, whose names were time-stamped (in this case with date +%b[...]).

I want to write a POSIX compliant one-liner that will:

either

  • skip lines output from ls -ltc that have 2 fields or less (as seen by awk) and do not contain the regexp constant /Jul/

or

  • skip the first line output by ls -ltc and any line not matching /Jul/.

The result is the same for my purpose as only the first line consists of two fields (as seen by awk).

I tried:

> ll -tc | rm $(awk --posix 'NF > 2 && !/Jul/ {print $NF;}')
> ll -tc | rm $(awk --posix 'NF > 2 !/Jul/ {print $NF;}')

Both have bad syntax because a condition on NF apparently does not coexist nicely with a regexp matching condition the way ls | awk '/foo/ && /bar/'would for instance.

Can sb give me pointers on how to either skip any arbitrary record and/or apply the arithmetic condition on NF and the regexp pattern matching at the same time ? I did look around but could not find the documented syntax I am looking for...

Cbhihe
  • 2,731
  • 3
  • 24
  • 47
  • *"both have bad syntax because... "* What is the actual error message? it's your shell syntax that looks wrong to me - rather than your `awk` syntax – steeldriver Jul 06 '15 at 23:36
  • @steeldriver; actually my syntax WAS wrong. I noticed it when I saw that @kos proposed the same thing as my 1st one liner only with `'NF>2 [...]`' instead of `'NF > 2 [...]'` . I.e. there should be no space left and right of the "greater than" arithmetic operator. – Cbhihe Jul 07 '15 at 07:01
  • And why not `find … -delete`? – A.B. Jul 07 '15 at 07:06

2 Answers2

3

Either

awk 'NF<=2 || /Jul/ {next} {print}'

or

awk 'NR==1 || /Jul/ {next} {print}'

or, inverting the logic to shorten the commands, either

awk 'NF>2 && !/Jul/ {print}'

or

awk 'NR!=1 && !/Jul/ {print}'
~$ cat input
first line
Gen second third
Feb second third
Mar second third
Apr second third
May second third
Jun second third
Jul second third
Aug second third
Sep second third
Oct second third
Nov second third
Dec second third
~$ awk 'NF<=2 || /Jul/ {next} {print}' input
Gen second third
Feb second third
Mar second third
Apr second third
May second third
Jun second third
Aug second third
Sep second third
Oct second third
Nov second third
Dec second third
~$ awk 'NR==1 || /Jul/ {next} {print}' input
Gen second third
Feb second third
Mar second third
Apr second third
May second third
Jun second third
Aug second third
Sep second third
Oct second third
Nov second third
Dec second third
kos
  • 35,535
  • 13
  • 101
  • 151
  • The next awk profi? ;) +1 – A.B. Jul 07 '15 at 04:49
  • 1
    @A.B. I guess with "profi" you mean "professional" (translated with Google Translate from German), however yes. Some tasks are just *designed* for `awk`. ;) – kos Jul 07 '15 at 04:56
  • OK, professional :) – A.B. Jul 07 '15 at 04:57
  • +1 for `awk 'NF>2 && !/Jul/ {print}'` <= ok, that's what I was looking for. ...... `awk 'NF<=2 || /Jul/ {next} {print}'` <= nice ! I did not know `{next}`. It cuts it nicely. – Cbhihe Jul 07 '15 at 07:08
1

@Kos has given an absolutely correct answer to your question.

But I think that you're trying to solve a problem that is not a problem. To delete files that match a certain criteria, you should use find with the parameter -delete.

eg:

find . -type f -newermt 2015-07-07  ! -newermt 2015-07-08 -delete
find . -type f -newerat 2015-07-07  ! -newerat 2015-07-08 -delete
A.B.
  • 89,123
  • 21
  • 245
  • 323
  • Yes, you are right "in general". However I need to use awk not just to delete files but to perform other tasks as well. I simplified the one liner so my question would not be muddled by unnecessary details. I do thank you though. What you suggest is useful. If my objective was only to delete files that verify a certain date base criteria, yours would be the solution of choice. – Cbhihe Jul 07 '15 at 11:41