15

How do I recursively remove files that are less than 1MB in size from a directory?

Dan D.
  • 5,964
  • 2
  • 37
  • 40
  • 2
    Possible duplicate of [How do I delete all files smaller than a certain size in all subfolders?](http://superuser.com/questions/644272/how-do-i-delete-all-files-smaller-than-a-certain-size-in-all-subfolders) – That Brazilian Guy May 31 '16 at 14:56

5 Answers5

25

This can be done with find:

find . -type f -size -1M -exec rm {} +

Note that this will recursively descend into subdirectories, and will unconditionally delete all files smaller than 1 megabyte. Be careful.

Sven Marnach
  • 401
  • 3
  • 8
  • you're missing the path argument to `find` –  Feb 08 '12 at 12:25
  • @Useless: That's GNU `find`. :) – Sven Marnach Feb 08 '12 at 12:29
  • I never knew it let you omit that! –  Feb 08 '12 at 12:31
  • @Useless: It does, but other versions of `find` don't, so if you want portability, you should include a directory argument. – Sven Marnach Feb 08 '12 at 12:35
  • I would recommend `-delete` instead of `-exec rm`, since the latter will have corner-case problems with file names contaning weird characters (even newlines could appear), but mostly since it will die if the number of files is very large (>`getconf ARG_MAX`). This has happened to me when using `rm *` to clear a browser cache directory, and I think it applies in this case as well (if not, please feel free to tell me why). – Daniel Andersson Feb 13 '12 at 11:03
  • 2
    @DanielAndersson: `find` restricts the number of arguments to the called process to fit into the system's limits, in contrast to `rm *`, which is guranteed to be a single process invocation. `find` will invoke multiple instance of `rm` if necessary. And I'm pretty sure that special characters are treated correctly, including newline characters. I prefer `-exec rm` over `-delete` for flexibility reasons -- as an example, the latter offers no way to delete write-protected files. – Sven Marnach Feb 13 '12 at 11:57
  • You are correct, and I thank you for your comment. `-exec +` takes ARG_MAX into account, and I have not seen any file name problems with `{}` in `find`. – Daniel Andersson Apr 04 '12 at 10:30
  • 1
    @Invoker: I reverted your change since it was incorrect. `-1M` means less than one megabyte as desired. Your version would delete all files with exactly one megabyte in size, which seems to be a somewhat pointless operation. – Sven Marnach Oct 05 '15 at 15:28
  • 2
    For anyone interested, if you want to remove all files _greater than_ 1M, use the command `find . -type f -size +1M -exec rm {} +`. Note the +1M instead of -1M. – chessofnerd Oct 06 '15 at 20:36
11

This should do the job:

$ find <directory> -type f -size -1M -delete
jcollado
  • 266
  • 1
  • 6
2

Just for variety and a possible (probably marginal) performance gain:

find <directory> -type f -size -1M -print0  | xargs -0 rm
Useless
  • 278
  • 1
  • 4
  • How is this supposed to be faster? It starts an additional `xargs` process. – Sven Marnach Feb 08 '12 at 12:33
  • Now you can have _two_ CPUs contending for the same block device! More sensibly, the stat/readdir operations aren't synchronously blocked by the unlink operation. Whether this is likely to be better obviously depends on the subtree size, number of files, device etc. –  Feb 08 '12 at 12:36
1

Try

find . -size -1M -exec rm {} \;

ahvargas
  • 111
  • 2
  • 1
    This is great for non-GNU users. Thanks! the same as @Sven's answer, but with `\;` at the end instead of `+` – hamx0r Aug 18 '16 at 18:16
-1

You can checkout this link http://ayaz.wordpress.com/2008/02/05/bash-quickly-deleting-empty-files-in-a-directory/ , it has exactly what you want.

for file in *;
  do
    file_size=$(du $file | awk '{print $1}');
    if [ $file_size == 0 ]; then
        echo "Deleting empty file $file with file size $file_size!";
        echo "rm -f $file";
    fi;
done

You can iterate through all the files with a for loop and then use du and awk to find the filesize like in the above example.

Steen Schütt
  • 496
  • 6
  • 15