Fattaneh Talebi
Fattaneh Talebi

Reputation: 767

List the directories whose the file sizes are all within a range

I want to list the directories containing whose the file sizes are all in within a range. My solution is to look at each directory and if its all file sizes where in the range, show that in out. I want to know if there exist an easier way to check like a switch in find command or any other command like this.

for example: the range= 10 - 20

dir1:
f1 size=12
f2 size= 19

dir2:
f3 size=22
f4 size=11

OUTPUT = dir1

dir2 is excluded because f3 is outside the 10-20 range. dir1 is not excluded, because all its files have sizes inside the range.

Upvotes: 6

Views: 690

Answers (2)

Peter Cordes
Peter Cordes

Reputation: 364338

Borrowing code from 4ae1e1's comment:

Find the first exception to the rule (if any) in each command-line-specified subdirectory. Print that if it's allowed.

dir_filesize_rangefilter() {
    # args: lo hi  paths...
    # sizes in MiB
    # return value: dir names printed to stdout
    local lo=$1 hi=$2
    shift 2  # "$@" is now just the paths

    for dir; do   # in "$@"   is implicit
        local safedir=$dir
        [[ $dir = /* ]] || safedir=./$dir   # make sure find doesn't treat weird -filenames as -options
        # find the first file smaller than lo or larger than hi
        [[ -z "$(find "$safedir" -type f 
               \( -size "-${lo}M" -o -size "+${hi}M" \)
               -print -quit )"
        ]] && printf '%s\n' "$dir"
    done
}

I used "printf" because "echo" breaks if one of the directory names starts with -e or something. You could have this add allowed directories to an array, instead of printing them to stdout, if you really want to be paranoid about valid filenames (since you'd have to parse the output of this with an while IFS= read loop or something to allow any character, and that still breaks on dir names containing a newline.)

Apparently SO's syntax highlighting doesn't know the quoting rules for quotes inside $(command substitution) :/

Upvotes: 2

proteus
proteus

Reputation: 36

Here is a possible solution in 3 lines. I give it in a concrete example:

  1. List of all files greater than 1MB into a file: du -hat 1M > gr.dat

  2. List of all files smaller than 3MB into a different file: du -hat -3M > sm.dat

  3. Use grep to find matches in both generated files: grep -F -x -f gr.dat sm.dat

Upvotes: 1

Related Questions