How to delete files filtered out by awk

24,531

Solution 1

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.)

Solution 2

In zsh, to remove all files of size 26 in the current directory (first line) or the current directory and its subdirectories (second line), use the L glob qualifier:

rm *(L26)
rm **/*(L26)

With GNU or FreeBSD/NetBSD/OSX find:

find . -name . -o -type d -prune -o -type f -size 26c -exec rm {} +
find . -type f -size 26c -exec rm {} +

Portably:

find . -name . -o -type d -prune -o -type f -exec sh -c '[ $(wc -c <"$0") -eq 26 ] && rm -- "$0"' {} \;
find . -type f -exec sh -c '[ $(wc -c <"$0") -eq 26 ] && rm -- "$0"' {} \;
Share:
24,531

Related videos on Youtube

Preeyah
Author by

Preeyah

Professional Software Testing Engineer specializing in automation with Open Source tools. Interested in: Test automation: Selenium, BDD, Cucumber Programming: Java, Python, Spring Data scraping Audio: recording/mixing

Updated on September 18, 2022

Comments

  • Preeyah
    Preeyah over 1 year

    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?

    • sr_
      sr_ about 12 years
      Btw, find could also do this, i.e. something like find . -maxdepth 1 -size 46c -delete (at least GNU find can)
    • Preeyah
      Preeyah about 12 years
      @sr_ That's an interesting option. I will keep that in mind. Thanks!
    • jw013
      jw013 about 12 years
      Please don't parse ls output. @sr_ You should post that as an answer.
    • jw013
      jw013 about 12 years
      @EugeneS ... except sr_ has already shown you exactly how to do this safely with find. Why don't you just use the suggested command? It is never necessary to use ls for manipulating files (at least I have yet to run into such a situation) since find and shell globbing cover nearly all cases.
  • Preeyah
    Preeyah about 12 years
    Thank you for your answer and mentioning ALL the bugs! You're absolutely right, it works fine now. Regarding the -ltr, I guess it's just a bad habit.
  • geekosaur
    geekosaur about 12 years
    Also note the comment above about parsing ls output, which I let pass; it is really not a good idea, due to the possibility of spaces and other special characters in filenames.
  • Preeyah
    Preeyah about 12 years
    I know that but I couldn't think about a way to avoid this. If you can edit your answer and describe a way to perform this task without using ls I will be grateful. Thanks again!
  • jippie
    jippie about 12 years
    I would advise using $NF (always referring to the last field) instead of $9.
  • geekosaur
    geekosaur about 12 years
    @jippie, that's still not going to work if there's whitespace in the name.