147

I have a folder with many sub-folders containing small tif files (less than 160kb) which have been merged together in bigger pdf files, together with some big multi-page tif files.

I want to delete all small tif files without deleting the bigger files (tif or pdf) and retaining the directory structure. How do I go about it on Linux using the command-line?

1 Answer 1

238
find . -type f -name "*.tif" -size -160k -delete

This will search recursively (in the current directory and all subdirectories) for files with filenames matching the glob *.tif and size smaller than 160 kilobytes and then delete them.

Run the command without -delete first. It will just list the files instead of deleting. This way you can verify the correct files are to be deleted.


Explanation:

A typical find command looks like this

find dirname -test a -test b -action

we start with all files (and all directories) in dirname. then the tests filter the files (and directories) based on some criteria. the tests work in series. so the second test gets the result from the first test. the action then does things with the final result. if no explicit action is given then it is default -print (print the filename including path to file).

in our case:

find . -type f -name "*.tif" -size -160k -delete

we start in current directory (the dot: .); filter out directories (-type f); filter by name; filter by size; and ultimately delete those files.

now explanation for each part. for brevity will i will only say "files" from now on instead of "files and directories".


find . -type f -name "*.tif" -size -160k -delete
                                         ^^^^^^^

This is the action. As the name says it instructs find to delete the files found.

A directory will only be deleted if it is empty. In our case it does not matter because we filtered out directories.

Other common actions are -printf (to print based on custom format) or -exec (to execute a command on the found file). There is also -ls which will print the files found in a format similar to the command ls.

As mentioned above: if you leave out the action then the default action is -print


find . -type f -name "*.tif" -size -160k -delete
                             ^^^^^^^^^^^

This test filters the files based on size. This is the relevant part for this question.

Note the - before 160k. Just 160k means exactly 160 kilobytes. -160k means smaller than 160 kilobytes. +160k means larger than 160 kilobytes.

If you want smaller and equal to 160k then do -161k.

If you want to filter size in bytes (as in 160 bytes instead of 160 kilobytes) then you have to write it like this: 160c. If you just write 160 it will be interpreted as 160*512 bytes. This is a strange requirement by POSIX. Read here for more details: https://unix.stackexchange.com/questions/259208/purpose-of-find-commands-default-size-unit-512-bytes


find . -type f -name "*.tif" -size -160k -delete
               ^^^^^^^^^^^^^

This test filters the files based on filename.

The pattern is a glob. It works like you would expect in a typical command like for example rm *.tif.

Be carefull to put the glob in quotes ("*.tif"). Otherwise the shell will expand the glob before find gets the arguments and it will execute a completely different command. See here for more information about quoting the glob: https://unix.stackexchange.com/questions/82139/what-is-the-difference-between-pl-and-pl-in-grep-why-does-quoting-change

There are several tests that filter agains the "name" of a file: -name matches against the filename regardless of the path to the file. -path matches against the filename and the path to the file. and -regex which uses regular expression instead of glob to match against filename including path.

for more info on glob and regex read this article https://www.linuxjournal.com/content/globbing-and-regex-so-similar-so-different or search for "difference glob regex"


find . -type f -name "*.tif" -size -160k -delete
       ^^^^^^^

This test filters based on type. In this case we request it to only filter for files.

If you leave this test out you get both files and directories.

Typically you will want to filter only files or only directories as many filters and actions only make sense on files or directories.

To filter only directories use -type d.


find . -type f -name "*.tif" -size -160k -delete
     ^

the dot (.) stands for the current directory. you can also search another directory in the current directory

find some/dir -type f -name "*.tif" -size -160k -delete

or an absolute path somewhere on the system

find /absolute/path -type f -name "*.tif" -size -160k -delete

on sane versions of find (GNU find) you can leave out the dot and it will search in the current directory by default. practically all linuxes use the GNU version of find. some overpriced non-free systems (Mac OS X) use outdated and/or inferior versions of find just to avoid the GPL (the perpetualy free license of GNU and linux).

see here for more info on apple avoiding GPL: http://meta.ath0.com/2012/02/05/apples-great-gpl-purge/


bonus!

if you want to exclude subfolders, or in other words: not recursively, then do it like this

find . -maxdepth 1 -type f -name "*.tif" -size -160k -delete
       ^^^^^^^^^^^

this will tell find to not look deeper than one level. in effect it will not go down subdirectories.

9
  • The ubuntu man page seems to mention this. Just below the "TESTS" section: Numeric arguments can be specified as +n for greater than n, -n for less than n, n for exactly n.
    – jdg
    Commented Sep 11, 2014 at 23:55
  • 1
    thanks. it did not occur to me that the information might be somewhere else in the manpage.
    – Lesmana
    Commented Sep 12, 2014 at 8:55
  • It is nice this command also works recursively. My use case would be to delete .txt files under 12kB.
    – Sun
    Commented Sep 23, 2014 at 4:21
  • no need for sudo? Commented Oct 6, 2015 at 15:35
  • 23
    For sizes in bytes specify 50c, not 50b or 50!
    – Evengard
    Commented Jan 29, 2016 at 13:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .