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.

Which command will print the sizes of all files and directories in the tmp directory (including hidden ones) and sort them by sizes from largest to smallest in human readable format (e.g. 2 GB)?

The output could be as follows:

file.mpg 2GB
file.avi 1.8GB
.backtup 1.7 GB (this is directory)

I tried to use the ls and du commands but was not able to find the right switches.

share|improve this question

6 Answers 6

up vote 3 down vote accepted

Here's a quick fix, use du + sort. Try this:

du -smc * | sort -n

This will ignore hidden files, but that's another easy fix:

du -smc .[^.] .??* * | sort -n

This may cause warnings about if one or more of the above patterns don't match a file. The first pattern .[^.] matches all two character filenames starting with . except for .., the second pattern, .??* matches all three letter or more filenames starting with . and * matches all files not starting with . For a more sophisticated listing such as finding all file larger than X across a whole filesystem, or maintaining a list of filesystem growth, I have some DIY shell script I've written and can share if your interested.

share|improve this answer
    
Thank you. I'm interested in your script if you will be so kind. –  xralf Apr 6 '11 at 19:18
    
Use sort -nr if you want the biggest values on top. –  ultrasawblade Apr 7 '11 at 2:55

To list the files anywhere under /tmp, sorted by size:

find /tmp -type f -exec du -k {} + | sort -k1n -k2

To list the files and directory trees immediately under /tmp, sorted by size:

du -k /tmp/..?* /tmp/.[!.]* /tmp* 2>/dev/null | sort -k1n -k2

To list all files and directory trees anywhere under /tmp, sorted by size:

du -ak /tmp | sort -k1n -k2

(An example to illustrate the difference between the three commands: if there's a file /tmp/dir/file, the first command lists /tmp/dir/file, the second lists /tmp/dir, and the third lists both.)

All the commands above show sizes in kilobytes. While GNU du can output “human-readable” sizes (with k, M, G, etc. multipliers), sorting them is another matter. Recent enough GNU coreutils (≥7.4) can do it: just replace du -k with du -h and sort -k1n -k2 with sort -k1h -k2. Otherwise, here's a crude awk script to convert to suffixed sizes (rounding down); just pipe the sort output above into it.

awk -vFS='\t' -vOFS='\t' '{
    if ($1) $1 = substr($1,1,(length($1)-1)%3+1)
                 substr("kMGTPEZY",(length($1)-1)/3+1,1);
    print}'
share|improve this answer
    
Thank you. Those commands are useful, but I'm interested only in the files and directories directly under tmp, not files in subdirectories –  xralf Apr 7 '11 at 13:31
1  
@xralf: Then use only the second form of du call. –  Gilles Apr 7 '11 at 19:59
    
Looks good, but better result is with MB and GB as forcefsck posted. –  xralf Apr 8 '11 at 7:34

I'm using following alias for it: alias ds='du -x --all --max-depth=1 . | sort -n'

It prints sizes of all files and 1-st level subdirectories of current dir.

share|improve this answer
    
It's nice short solution, but it print only directories. –  xralf Apr 7 '11 at 18:22
    
Oh, sorry, you are right. I've never faced this problem with files. Howewer, I've found how to make it work with files: using --all swicth. –  rvs Apr 8 '11 at 6:57
    
Great correct solution. penguin359 has slightly better because it shows the sizes in MB. The best would be forcefsck's solution but his solution omits directories with spaces. –  xralf Apr 8 '11 at 7:51

With the current version of gnu sort (and borrowing @penguin359 file pattern)

cd /tmp; du -sShc .[^.] .??* * | sort -h

With an older version of sort

cd /tmp
foo=$(du -sShc .[^.] .??* *)
for u in K M G T; do
    echo "$foo" | egrep "^[0-9\.]+$u" | sort -n
done

EDIT: added -S parameter to du to not include subdirectories.

share|improve this answer
    
I wanted rather disk space used by files and directories (total size of data inside) directly under tmp (not subdirectories). My sort command does not have -h option. –  xralf Apr 7 '11 at 13:40
    
I'm not 100% sure what you mean, since you had already accepted an answer with the same file pattern selection. Edited my post to not include subdirs. If you want the apparent size and not the actual disk space used, you may add --apparent-size to du parameters. –  forcefsck Apr 7 '11 at 18:00
    
Now it works nice. I only have to look for GB and then MB, but it's not a problem. –  xralf Apr 7 '11 at 18:29
    
I had the unit letters in the wrong order, now fixed. If you want the order from big to small, change the order of the unit letters and add -r to sort. –  forcefsck Apr 7 '11 at 19:07
    
I noticed, it forgot to print the size of directory (without . prefix) –  xralf Apr 7 '11 at 19:24

UPDATE: I've scrapped the previous script. Here is a new version, using du and awk (the previous one used tree and sed)

This is the output of: dusort ~/test 1

================
dir     4.10 KiB  /home/user/test/bdir
dir     4.98 KiB  /home/user/test/Kdir
dir   104.91 MiB  /home/user/test/Mdir
dir   587.47 MiB  /home/user/test/Gdir
dir   692.39 MiB  /home/user/test
================
 f      0    Byt  /home/user/test/new file
 f     42    Byt  /home/user/test/.hi   dd     en
================

Here is the script

units() { awk -v pfix="$1" \
  'BEGIN { yect=6  # Array element-count
    split("Byt KiB MiB GiB TiB PiB",lbl)
    for (i=1;i<=yect;i++) { val[i] = (2**(10*(i-1)))-1 } 
  }
  { yess=yect  # Array element-subscript
    while ( $1 < val[yess] ){ yess-- }
    num = $1 / (val[yess]+1)
    sub(/^[0-9]*\t*/,"")
    if (yess!=1) { printf "%s %8.2f %s  %s\n", pfix, num, lbl[yess], $0 }
    else        { printf "%s %5d    %s  %s\n", pfix, num, lbl[yess], $0 }
   }'
}
tdir="/tmp/$USER/$(basename $0)"
[[ ! -d "$tdir" ]] && mkdir -p "$tdir"
file="$tdir/$(date +%N)"
echo "================"
dirs="$file.dirs";   du --max-depth=$2 -b $1  >"$dirs" ; <"$dirs"  sort -n           | units "dir"
echo "================"
filz="$file.filz"; { du --max-depth=$2 -ab $1 ; cat "$dirs" ; } | sort -n | uniq -u  | units " f "
echo "================"
rm   "$file."* 
#
share|improve this answer
    
When you say sizes of all files and directories,do you mean the space each item takes up on the disk (eg. on my Ubuntu ext4 filesystem, an empty directory takes 4k of disk-space, and a file smaller than 4k takes up 4k. The minimum allotment chunk is 4k).. or do you mean the amount of data in each file, eg, 100(bytes).. And for directories, do you want to know the total of file data in that directory.. If you do want the size of data inside files, then tree does that. if you want the disk-space used, then du does that... (tree doesn't total a directory) –  Peter.O Apr 7 '11 at 12:17
    
'du' is the better choice... I've just noticed in man du, that it can also report the "apparent file size".... The apparent size of a file is the number of bytes reported by wc -c' on regular files, or more generally, ls -l --block-size=1' or stat --format=%s'. For example, a file containing the word zoo' with no newline would, of course, have an apparent size of 3. –  Peter.O Apr 7 '11 at 12:50
    
I wanted rather disk space used by files and directories (total size of data inside) directly under tmp (not subdirectories) –  xralf Apr 7 '11 at 13:34
    
I'm sorry, I'm not in the stage of shell scripting I could understand it yet, so I let it to other users to decide how good answer it is. Thank you for your work. I will study it when I'm better. –  xralf Apr 8 '11 at 7:43
find /tmp -exec du {} + | sort -nr | less 

shows biggest files first, so you can quit as soon as you've seen enough.

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.