36

I'm wondering if we can combine the honesty of 'du' with the indented formatting of 'tree'. If I want a listing of the sizes of directories:

du -hx -d2

...displays two levels deep and all the size summaries are honest, but there's no indenting of subdirs. On the other hand:

tree --du -shaC -L 2

...indents and colorizes nicely however the reported sizes are a lie. To get the real sizes one must:

tree --du -shaC

...which is to say that you only get the true sizes if you let 'tree' show you the entire directory structure. I'd like to be able to always have correct size summaries regardless of how many levels of subdirs I want to actually display. I often do this:

tree -du -shaC | grep "\[01;34m"

... which prunes out everything but directories, and indents them nicely ... but there's no easy way to limit the display to just a given number levels (without the summaries lying). Is there a way? Perhaps I've missed the correct switches ...

2
  • 1
    I wish there was a tool that visualizes du output (i.e. doesn't need to do its own scanning, but you can just save the ouptut of du and pipe it into a graphical tool). Commented May 8, 2020 at 21:11
  • The last command is missing a dash (should be --du not -du)! If you could edit it that'd be great!
    – Shayan
    Commented Mar 12, 2022 at 18:02

6 Answers 6

18

Also checkout ncdu: http://dev.yorhel.nl/ncdu

Its page also lists other "similar projects":

gt5 - Quite similar to ncdu, but a different approach.

tdu - Another small ncurses-based disk usage visualization utility.

TreeSize - GTK, using a treeview.

Baobab - GTK, using pie-charts, a treeview and a treemap. Comes with GNOME.

GdMap - GTK, with a treemap display.

Filelight - KDE, using pie-charts.

QDirStat - KDE, with a treemap display.

QDiskUsage - Qt, using pie-charts.

xdiskusage - FLTK, with a treemap display.

fsv - 3D visualization.

Philesight - Web-based clone of Filelight.

4
  • 1
    Thanks David, finally got around to looking at those. I picked ncdu. Commented Nov 18, 2015 at 1:20
  • @David where does tdu come from ?
    – shirish
    Commented Jan 27, 2017 at 21:10
  • @shirish Refer to my source, noted above Commented Mar 30, 2017 at 16:49
  • Even though duc is not a treemap, I find that Sunburst charts are often better than treemaps. Commented May 8, 2020 at 21:10
11

You don't need to grep for the colour code, the -d option is list directories only.

This seems to do what you want:

$ tree --du -d -shaC | grep -Ev '(  *[^ ]* ){2}\['
.
├── [  18]  dir1
├── [  30]  dir2
├── [ 205]  junk
│   ├── [  18]  dir1
│   ├── [  30]  dir2
│   └── [  76]  dir3
├── [ 119]  merge
└── [  20]  stuff

 4.4K used in 10 directories

The grep command removes all lines that have (one or more spaces followed by a non-space followed by a space) twice, followed by a [.

If you want a depth of 1, change the bound count inside the {} curly braces to {1} rather than {2}. same if you want a depth of 3, change it to {3}.

You can turn this into a shell function, like so:

mytreedu() {
  local depth=''

  while getopts "L:" opt ; do
      case "$opt" in
          L) depth="$OPTARG" ;;
      esac
  done

  shift "$((OPTIND-1))"

  if [ -z "$depth" ] ; then
      tree --du -d -shaC "$@"
  else   
      local PATTERN='(  *[^ ]* ){'"$depth"'}\['
      tree --du -d -shaC "$@" | grep -Ev "$PATTERN"
  fi
}

This uses getopts to "steal" any -L option and its argument from the tree command line, if there is one. If there isn't a -L n option on the command line, then that works too.

All other options and args are passed to the tree command.

The local PATTERN=... line isn't really necessary. I only did it like that to make sure that it would fit on one line and not word-wrap here on U&L. The regular expression could and probably should just go directly on the tree | grep ... line.

Run it like this:

mytreedu 

or

mytreedu -L 2 /path/to/dir/
6
  • 3
    I love the code, but repeat that you can't use the '-d' because if you do, the size summaries are incorrect, or at least they are here. The size will be reported always as '4096' which is the size of the entry for the dir itself, but not the size of all it's contents. Commented Oct 25, 2015 at 15:41
  • ... should have said '4096' for each directory under the current directory ... but you don't get the sizes of the dir including it's files. Commented Oct 25, 2015 at 15:48
  • you only mentioned -L as being a problem, didn't mention -d at all. Now that I look more closely at the numbers reported, neither tree --du nor tree --du -d report sizes that in any way resemble those reported by du.
    – cas
    Commented Oct 25, 2015 at 19:47
  • Point being that anything less than a 100% display will not give you correct sizes. You could limit via '-d' or '-L 2' or whatever else--it it isn't shown, it isn't counted in the size. Commented Oct 26, 2015 at 0:17
  • tree --du doesn't seem to give correct sizes for directories anyway, with or without -d or -L. I have no idea what the numbers are supposed to be, but they're unrelated to what du reports.
    – cas
    Commented Oct 26, 2015 at 0:30
8

You can use dutree

enter image description here

  • coloured output, according to the LS_COLORS environment variable.
  • display the file system tree
  • ability to aggregate small files
  • ability to exclude files or directories
  • ability to compare different directories
  • fast, written in Rust
4

There isn't any perfect command tool to do this, But I found two ways that are closly.

  • shows both folders and files' size, but not showing in a tree mode.

    du -ah --max-depth=1 /var/log

  • shows in tree mode but only files' size, the folders are in counts

    tree -ah /var/log -L 1

1

Version

$ tree --version;
# tree v2.1.1 © 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher,
# Florian Sesser, Kyosuke Tokoro

Command

# -x - Stay on the current file-system only...
# -a - All files are printed... (those beginning with a dot `.')...
# -p - Print the file type and permissions for each file...
# -u - Print the username, or UID...
# -g - Print the group name, or GID...
# -h - Print the size of each file but in a more human readable way...
# -F - Append a `/' for directories, a `=' for socket files...
# -D - Print the date of the last modification time...
# --du - For each directory report its size as the accumulation of sizes...
# --dirsfirst - List directories before files...
# --charset - Set the character set to use when outputting...
# --sort - Sort the output by type instead of name...
# --timefmt - Prints... and formats the date according to the format string...
#
tree -xapughFD \
    --du --dirsfirst \
    --charset='ascii' --sort='size' --timefmt='%Y-%m-%d_%H-%M-%S' -- \
    . \
    | grep -P '^(?:\|\s{3}|\s{4}){0,1}(?:`|\|)\-\-';

In the grep regex, {0,1} (frankly, is similar to ?) may be used for the "depth". For example, {0,3} would be for the current and maximum of 3 directories into deep.

Example

$ pwd -P;
/home/user
$ tree -xahpugFD --du --charset=ascii --dirsfirst --sort=size --timefmt='%Y-%m-%d_%H-%M-%S' -- '/usr/share/vlc' | grep -P '^(?:\|\s{3}|\s{4}){0,1}(?:`|\|)\-\-';
|-- [drwxr-xr-x root     root     520K 2022-10-23_09-19-24]  lua/
|   `-- [drwxr-xr-x root     root     516K 2022-10-23_09-19-24]  http/
|-- [drwxr-xr-x root     root     210K 2022-10-23_09-20-57]  skins2/
|   |-- [drwxr-xr-x root     root     4.1K 2022-10-23_09-20-57]  fonts/
|   |-- [-rw-r--r-- root     root     160K 2022-03-13_10-00-10]  default.vlt
|   |-- [-rw-r--r-- root     root      31K 2022-03-13_10-00-10]  winamp2.xml
|   |-- [-rw-r--r-- root     root      10K 2022-03-13_10-00-10]  skin.dtd
|   `-- [-rw-r--r-- root     root      167 2022-03-13_10-00-10]  skin.catalog
|-- [drwxr-xr-x root     root     6.1K 2022-10-23_09-19-24]  utils/
|   |-- [-rwxr-xr-x root     root      873 2022-03-13_10-00-10]  gnome-vlc-default.sh*
|   |-- [-rwxr-xr-x root     root      620 2022-03-13_10-00-10]  audio-vlc-default.sh*
|   `-- [-rwxr-xr-x root     root      620 2022-03-13_10-00-10]  video-vlc-default.sh*
`-- [-rw-r--r-- root     root      71K 2022-03-13_10-00-10]  vlc.ico
0
0

Inspired by cas, I'm now doing this:

treee ()
{
    integer levels=$(( ($1 + 1) * 4 ))
    tree --du -shaC | grep "\[01;34m" | grep -Ev "^[^\[]{$levels}\[*"
    du -sh .
}
5
  • if you're going to throw away all the getopts stuff, you should at least still have "$@" immediately after the -shaC. otherwise that function is hard-coded to work for the current directory only.
    – cas
    Commented Oct 25, 2015 at 19:50
  • Once we got the thing working, I was going to ask you about that: please elaborate. Right about "$@" of course, but so far I only ever use it in the current dir, so haven't noticed that yet. All this 'getopts' stuff is new to me, I'd like to know what you are thinking there. Commented Oct 26, 2015 at 0:14
  • One of the benefits of using getopts is that options can appear in any order on the command line. The initial version of the mytree function I wrote used "$1" just as yours did, so the depth argument had to be the first argument, and it was not optional. I decided that wasn't good enough so used the bash-builtin getopts to process the -L option. This allowed the -L n option to appear anywhere on the command line. It also allowed it to be completely optional.
    – cas
    Commented Oct 26, 2015 at 0:24
  • another way of looking at it is that getopts allows you to write scripts that take real options and arguments (rather than just args in hard-coded positions like $1 $2 $3 etc), just like most other programs on your system. And if you use the getopt program (note that's without an s) from the util-linux package you can use both short single-letter options (e.g. -l) and long options (like --long) just like GNU programs.
    – cas
    Commented Oct 26, 2015 at 0:26
  • Ah ... it comes back to me now. Yes, I actually used that once. Must take another look at it. Thanks. Commented Oct 26, 2015 at 6:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .