15

I'm getting output from du -h like the following:

103M    ./.wine/drive_c/windows/mono/mono-2.0/lib/mono
103M    ./.wine/drive_c/windows/mono/mono-2.0/lib
129M    ./.wine/drive_c/windows/mono/mono-2.0
129M    ./.wine/drive_c/windows/mono
362M    ./.wine/drive_c/windows
545M    ./.wine/drive_c

I'd like to only show the most actionable folder, which is the folder ./.wine/drive_c/windows/mono/mono-2.0/lib/mono

Is there any way of removing the parent folder if a child folder is responsible for most of the disk space usage?

A setting to only show leaf folders might do the trick, or a setting to subtract the size of all subfolders from a parent folder when calculating the size of the parent folder.

EoghanM
  • 887

7 Answers7

16

If you are using GNU du you can use the -S or --separate-dirs option to not include the size of subdirectories when calculating the usage for the parent.

Your du command may not support this option.

You can use this couple with sort to get the largest individual directories (assuming GNU tools):

du --separate-dirs -h . |sort -h
Craig
  • 694
  • This seems to satisfy the 'subtract the size of all subfolders from a parent folder when calculating the size of the parent folder' part of my query, so will likely accept! I'm not sure it's exactly satisfying my needs though (trying to find the most actionable folders to delete in order to retrieve space) – EoghanM Sep 19 '13 at 16:42
  • To find the most actionable folders, check this out: du -Sh . | sort -rh | head – smithfarm Jan 24 '23 at 19:08
10

Personally, I just combine it with the power of GNU sort:

du -ch | sort -h

This will cause the sizes to be sorted in a human readable format. For example:

$ du -h /usr/ | head -20 | sort -h
8.0K    /usr/src/linux-headers-3.2.0-3-common/include/misc
12K /usr/src/linux-headers-3.2.0-3-common/include/drm/i2c
12K /usr/src/linux-headers-3.2.0-3-common/include/net/netfilter/ipv4
16K /usr/src/linux-headers-3.2.0-3-common/include/net/netfilter/ipv6
20K /usr/src/linux-headers-3.2.0-3-common/include/net/phonet
28K /usr/src/linux-headers-3.2.0-3-common/include/acpi/platform
52K /usr/src/linux-headers-3.2.0-3-common/include/net/netns
60K /usr/lib32/libv4l
76K /usr/src/linux-headers-3.2.0-3-common/include/net/caif
96K /usr/src/linux-headers-3.2.0-3-common/include/scsi/fc
108K    /usr/src/linux-headers-3.2.0-3-common/include/net/bluetooth
112K    /usr/src/linux-headers-3.2.0-3-common/include/drm/ttm
148K    /usr/src/linux-headers-3.2.0-3-common/include/net/netfilter
264K    /usr/src/linux-headers-3.2.0-3-common/include/rdma
284K    /usr/src/linux-headers-3.2.0-3-common/include/acpi
596K    /usr/src/linux-headers-3.2.0-3-common/include/drm
608K    /usr/src/linux-headers-3.2.0-3-common/include/scsi
668K    /usr/games
6.3M    /usr/lib32/gconv
8.9M    /usr/lib32

From man sort:

   -h, --human-numeric-sort
          compare human readable numbers (e.g., 2K 1G)

It still shows the ones you don't care about, but it is now very easy to find the ones you do.

terdon
  • 242,166
  • No, that actually makes it worse, as now it shows 545M ./.wine/drive_c at the top of the list, even though that only contains folders and no files, and makes it harder to see how space is distributed among the (recursive) subfolders of drive_c because they don't appear consecutively in the list. – EoghanM Sep 19 '13 at 16:28
7

If you are just looking for a clearly-arranged view, I recommend the durep package.

Example output:

root@dogmeat:~# durep -td 4 -hs 50M /usr/
[ /usr     4.8G (0 files, 9 dirs) ]
   1.9G [###########                   ]  38.57% lib/
     463.6M [#######                       ]  24.46% x86_64-linux-gnu/
         102.3M [######                        ]  22.07% wine/
     276.2M [####                          ]  14.57% i386-linux-gnu/
          96.1M [##########                    ]  34.80% wine/
     222.4M [###                           ]  11.73% libreoffice/
         189.3M [#########################     ]  85.12% program/
     122.6M [#                             ]   6.47% chromium-browser/
          87.6M [#####################         ]  71.46% chromium-browser
      79.5M [#                             ]   4.19% virtualbox/
      79.4M [#                             ]   4.19% jvm/
          73.4M [###########################   ]  92.52% java-7-openjdk-amd64/
              73.4M [############################# ]  99.99% jre/
      75.7M [#                             ]   3.99% python2.7/
          58.4M [#######################       ]  77.21% dist-packages/
      58.9M [                              ]   3.11% firefox/
      52.2M [                              ]   2.75% libwireshark.so.2.0.2
   1.4G [########                      ]  29.56% src/
   1.2G [#######                       ]  26.03% share/
     211.6M [####                          ]  16.54% fonts/
         199.3M [############################  ]  94.18% truetype/
              84.2M [############                  ]  42.23% horai-umefont/
     174.6M [####                          ]  13.64% icons/
          91.5M [###############               ]  52.39% gnome/
              66.4M [#####################         ]  72.60% icon-theme.cache
      77.5M [#                             ]   6.05% gimp/
          77.5M [##############################] 100.00% 2.0/
              66.2M [#########################     ]  85.43% help/
      74.4M [#                             ]   5.82% virtualbox/
          56.9M [######################        ]  76.42% VBoxGuestAdditions.iso
      62.9M [#                             ]   4.91% doc/
 240.1M [#                             ]   4.89% bin/

Use the -td parameter to specify the maximum depth, and the -hs parameter to specify a minimum size for a folder to show up in the results.

4

If you're using du to a fixed depth, e.g. du -m -d 2 ., you could just mask out lines that do not reach your max depth like so:

du -m -d 2 . | sort -k1n | awk -F"/" 'NF==3'

In this case, I wanted a depth of 2 directories so I only kept the results with 3 fields as defined with awk keyword NF after specifying "/" as my field separator at the start.

2

Not really sure if this is what you want, but you can strip parent directories using GNU find's -execdir:

find . -type d -execdir du -ch "{}" \;

The -execdir option is similar to -exec but executes the command you supply in the subdirectory where find has found a file.

Joseph R.
  • 39,549
  • hmmm, that doesn't seem to work as you describe. I'm still getting lots of parent directories in the output. – EoghanM Sep 19 '13 at 16:30
1
find . -maxdepth 1 -type d | xargs -I {} du -s {} 2> /dev/null | sort -n
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
0

These both work for me:

 du -h | perl -ne '$n=()=$_=~m#/#g;  print unless $n > 2'
 du -h | perl -ne 'print unless ($n=()=$_=~m#/#g) > 2 '
Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
huw
  • 1
  • A little bit comment, to get the numbers matched, the match should be in a list context that why we need ( ). – huw May 28 '15 at 19:37
  • du -h | perl -ne 'print unless (()=$_=~m#/#g) > 2 ' – huw May 28 '15 at 19:38