How to delete files filtered out by awk

awkfindxargs

I have the following files in a directory:

-rw-r--r-- 1 smsc sys  46 Apr 22 12:09 bills.50.1.3G.MO.X.20120422120453.Z
-rw-r--r-- 1 smsc sys  28 Apr 22 12:15 bills.50.1.3G.MO.X.20120422120953.Z
-rw-r--r-- 1 smsc sys  46 Apr 22 12:20 bills.50.1.3G.MO.X.20120422121453.Z
-rw-r--r-- 1 smsc sys  46 Apr 22 12:25 bills.50.1.3G.MO.X.20120422121953.Z

Where the fifth column is the file's size. I wish to delete all files which size is 46. In order to filter out these files I used the following command:

ls -ltr | awk '$5 ~ /46/ {print $0}'

Which works fine. But now I want to delete all files which were filtered out, so I add the following to the above command:

ls -ltr | awk '$5 ~ /46/ {print $0}' | xargs rm

However it gives me the following error:

rm: invalid option -- w

It seems that I have to use find over ls so I will get the output in the below format:

./bills.50.1.3G.MO.X.20120421050453.Z
./bills.50.1.3G.MO.X.20120421154953.Z
./bills.50.1.3G.MO.X.20120419133452.Z

But then I have no way to filter the files by its parameters.
How this task could be done?

Best Answer

You have two bugs:

  1. You are comparing for a size that contains 46; you want it to be equal to 46.

  2. You are printing the entire line, when you want only the filename.

And an additional issue: what is the point of -ltr to sort the ls output when you aren't using the sort order?

You want to do something like

ls -l | awk '$5 == "46" {print $9}' | xargs rm

Except you don't want to do that, because while it might be safe at the moment, parsing ls output is unreliable. Use an appropriate tool such as

find . -maxdepth 1 -size 46c -delete # requires GNU find

(Doing this portably is more annoying, since POSIX find doesn't have -maxdepth or -size that operates in units other than blocks. Better to write a script in a Perl/Python/Ruby/etc. that can use a proper directory scan that won't get in trouble with special characters in filenames.)

Related Question