Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to find all users shown in the /home/ directory whose disk consumption is more than 500MB. The following command works as expected.

cd /home/ && du */ -hs
68K     ajay/
902M    john/
250M    websites/

From the above example, only 902M john/ should be returned.

How can I make the find command output the same results?

share|improve this question
    
I am looking for a solution that will work with "find" command. –  shantanuo May 19 '11 at 12:03
5  
Any particular reason why do you want to use find for this task? I would just do cd /home/ && du */ -ms | awk '$1 > 500 { print $0 }' –  vtest May 19 '11 at 14:01
    
Can you please post this as an answer? This seems to working. But how do I get human readable disk consumption figure? –  shantanuo May 23 '11 at 4:20

4 Answers 4

up vote 0 down vote accepted
+50

You can't do this only with find, because find acts on individual files, and doesn't have a concept of adding up file sizes. You could pipe the output of find into another tool, but why bother when du does most of the work?

du -sm */ | sort -k1,1n | awk '$1 > 500 { sub(/$/, "M", $1); print $0 }'

The awk test becomes messy when the "human-readable" suffix in included in the input, because you need to strip off the trailing "M" to do an integer comparison. For the output, personally I'd skip the "M" suffix, but that's what was requested.

share|improve this answer

Not sure why you want something like find, so here's a scriptlet that does what you ask in bash (but doesn't work like find):

max_size=$((500*1024))
cd /home/ && du -ks */ | while read size user ; do
  if [ $size -gt $max_size ] ; then
    echo "${user%/} exceeds quota"
  fi
done

Example: (with a smaller size):

$ du -sk */
2948    a/
4       a b/
640     b/
48      qt/

$ du -ks */ | while read size user ; do if [ $size -gt 600 ] ; then echo "${user%/} exceeds quota" ; fi ; done
a exceeds quota
b exceeds quota

The ${user%/} just removes the trailing slash for extra prettyness.

share|improve this answer
    
The first example worked as expected. In case of second command, the $size is treated as text and not as number. –  shantanuo May 17 '11 at 11:28
    
@shantanuo: I don't understand that comment. There is only one script above. –  Mat May 19 '11 at 16:50
    
@shantanuo What is your shell? Mat wrote that his answer is for bash. –  Daniel Beck May 20 '11 at 17:12

This will print the disk usage (in kb) for each user's files in dir regardless of where those files are:

find dir -printf "%u %b\n" | perl -n -e '@l = split; $sum{$l[0]} += $l[1]; END { foreach(sort(keys(%sum))) { print "$_ ",$sum{$_}/2," KiB\n"; }}'

The find command prints the owner and block count of each file and directory in dir. The perl command adds the usage into a hash keyed on the username, thus building a sum of each user's file sizes; and then the contents of the hash is printed out.

share|improve this answer

Posting as answer.

I have used du -ms to get consistent output that can be processed by awk without additional intervention. You are correct that human readable output is better, so the final output gets processed once again for that.

#!/bin/bash

######################################################################
#  AUTHOR: Joe Negron - LOGIC Wizards ~ NYC
#  LICENSE: BuyMe-a-Drinkware: Dual BSD or GPL (pick one)
#  USAGE: byteMe (bytes)
#  ABSTRACT: Converts a numeric parameter to a human readable format.
#  URL: http://www.logicwizards.net/2010/10/19/byteme-a-simple-binary-metrics-bash-script-howto-convert-bytes-into-kb-mb-gb-etc-using-bash-bc/
######################################################################
function byteMe() { # Divides by 2^10 until < 1024 and then append metric suffix
declare -a METRIC=('B' 'KB' 'MB' 'GB' 'TB' 'XB' 'PB') # Array of suffixes
MAGNITUDE=0  # magnitude of 2^10
PRECISION="scale=1" # change this numeric value to inrease decimal precision
UNITS=`echo $1 | tr -d ','`  # numeric arg val (in bytes) to be converted
while [ ${UNITS/.*} -ge 1024 ] # compares integers (b/c no floats in bash)
  do
   UNITS=`echo "$PRECISION; $UNITS/1024" | bc` # floating point math via `bc`
   ((MAGNITUDE++)) # increments counter for array pointer
  done
echo -n "$UNITS${METRIC[$MAGNITUDE]}"
}

cd /home/ && du */ -bs | awk '$1 > 500 { print $0 }' | while read LINE; do
    SIZE=$(echo "$LINE" | cut -f 1)
    HRSIZE=$(byteMe "$SIZE")
    DIR=$(echo "$LINE" | cut -f 2)
    printf "%8s %s\n" "$HRSIZE" "$DIR"
done

Notes:

  1. bash function was found by googling (see the comments)
  2. I have changed du -ms to du -bs, thus making it possible to use the conversion function that accepts bytes.
  3. The 500MB limit is still hardcoded. Feel free to modify the script to accept it as argument.
share|improve this answer

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.