Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to delete files which size is between certain values. For example I have the following list of files:

-rw-r--r-- 1 smsc sys  558 Apr 30 13:07 stats.sfe.1.20120430130513.xml.Z
-rw-r--r-- 1 smsc sys  388 Apr 30 15:32 stats.sfe.1.20120430153013.xml.Z
-rw-r--r-- 1 smsc sys  386 Apr 30 15:36 stats.sfe.1.20120430153513.xml.Z
-rw-r--r-- 1 smsc sys  389 Apr 30 15:42 stats.sfe.1.20120430154013.xml.Z
-rw-r--r-- 1 smsc sys  390 Apr 30 16:02 stats.sfe.1.20120430160013.xml.Z
-rw-r--r-- 1 smsc sys  385 Apr 30 16:12 stats.sfe.1.20120430161013.xml.Z

From the above list, I want to delete only the files which size varies between 386b and 390b. I know that I can use the following command to delete files which size exceed certain <size>:

find . -size +<size>-delete

But how can I add one more boundary for files which size is less than a given value?

share|improve this question
4  
find conditions are logically AND'd by default, so just tack on another -size option for the other bound. –  jw013 Apr 30 '12 at 15:05
    
@jw013 Great! That works for me. Thanks! Please post it as your answer and I will accept it. –  Eugene S Apr 30 '12 at 15:21
add comment

4 Answers 4

up vote 2 down vote accepted

A range is simply an upper bound AND a lower bound. From the find spec:

expression [-a] expression

Conjunction of primaries; the AND operator is implied by the juxtaposition of two primaries or made explicit by the optional -a operator. The second expression shall not be evaluated if the first expression is false.

So all you need to do is specify both size bounds before the -delete action.

share|improve this answer
1  
Nice job finding that in the find spec. –  uther Apr 30 '12 at 16:13
add comment

The -a in an explicit AND operator that allows you to conjoin two primaries. In this case creating a range using -size.

find . -size +386b -a -size -390b -exec rm -f {} \;

Note the size is a numeric argument that can optionally be prepended with + and -. From man 1 find:

   Numeric arguments can be specified as

   +n     for greater than n,
   -n     for less than n,
    n      for exactly n.
share|improve this answer
    
Thank you for your answer. However, as @jw013 mentioned in his comment, find conditions are logically AND'd by default. So I just added one more size condition and it worked fine! The final command looks like: find . -maxdepth 1 -size +358c -size -395c -delete –  Eugene S Apr 30 '12 at 15:15
    
Note that the + and - prefixes are not documented in man find, but rather in info find. –  l0b0 Apr 30 '12 at 15:21
    
@l0b0 Actually I can't find any reference to it in the info as well.. –  Eugene S Apr 30 '12 at 15:31
    
+n for greater than n, -n for less than n, n for exactly n. –  uther Apr 30 '12 at 15:36
add comment

Whenever find expects a number, you can put a + sign before it to mean more than this number, or a - sign to mean less than this number. These are strict inequalities: +3 and -7 means 4, 5 or 6.

With the -size primary, you need to add the suffix c to indicate that the number is a number of bytes. You can concatenate multiple primaries to take their conjunction (in some versions, you can put -a or -and between them). Thus:

find . -size +385c -size -391c -delete

In zsh, you can use the L glob qualifier. The default unit is bytes; like find, the characters + and - indicate strict inequalities.

rm *(L+385-391)

(The command above does not recurse into subdirectories; if you need that, add **/ before the pattern.)

share|improve this answer
add comment

One way using perl:

perl -e '
    for ( @ARGV ) { 
        if ( -s >= 386 && -s _ <= 390 ) { 
            unlink $_ or printf qq[%s\n], qq[Could not delete $_: $!] 
        } 
    }
' *
share|improve this answer
    
Thank you for your answer! Should this part of code be entered as a single line? –  Eugene S Apr 30 '12 at 15:13
    
@EugeneS: Yes. It should work pasting it in your command line as-is or joining all lines into one. –  Birei Apr 30 '12 at 15:16
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.