0

I have a directory with the following subdirectories, i.e. If I run $ tree -L 1

.
├── 2007-06-20_to_2008-10-01
├── 2008-07-21_to_2008_08_12-Nokia 2mp
├── 2009-11-01_to_2011-01-10 - All iphone Pics
├── 2011-01-01 palliser-pics
├── 2011-03-10_to_2011-04-12-few iphone pics b4 switch to HTC
└── 2011-03-31-to-2013-05-01 ALL HTC pics-backup-prior-to-factory-reset

I would like to see the amount of diskspace those 2 directories and all their contents take up.
e.g. desired output, something like

2.7G  2007-06-20_to_2008-10-01
200MB 2008-07-21_to_2008_08_12-Nokia 2mp
1.3G  2009-11-01_to_2011-01-10 - All iphone Pics
667MB 2011-01-01 palliser-pics
2.3G  2011-03-10_to_2011-04-12-few iphone pics b4 switch to HTC
123MB 2011-03-31-to-2013-05-01 ALL HTC pics-backup-prior-to-factory-reset

So I have been trying:

find .  -maxdepth 1 -type d | xargs du -h 

but because some of the directory names contain spaces each line from the find output is producing many WORD's before being passed to xargs, is it possible to fix this?

I know the root cause of the problem is caused by the spaces in the files, and I will use rename to fix if I cant find a way to get disksize with du, find and xargs

  • 1
    find . ! -name . -prune -type d -exec du -h {} + – mikeserv Nov 15 '15 at 06:06
  • thanks its an improvement, but that command is listing out all the subdirectories - and then seems to be looping back and re-producing that output another 4 or 5 times – the_velour_fog Nov 15 '15 at 06:13
  • ah you edited your comment. using {} + seemed to fix the looping issue - but its still printing the subdir's? – the_velour_fog Nov 15 '15 at 06:15
  • yeah, du does its own path traversal. user du -sh to summarize each argument. – mikeserv Nov 15 '15 at 06:19
  • then that summarises too much - it only du once producing one line of output containing the grand total for all directories. I guess -exec is the only option - but its obviously tricky to predict what arguments its going to use – the_velour_fog Nov 15 '15 at 06:24
  • how many directories per find match do you want exactly then? – mikeserv Nov 15 '15 at 06:24
  • just the top level dirs only, depth = 1. I have updated the question to show desired output – the_velour_fog Nov 15 '15 at 06:27
  • use find . -path '*/*/*/*' -prune -type -d -exec du -sh {} + – mikeserv Nov 15 '15 at 06:29
  • @mikeserv Using your ideas I finally got find . -maxdepth 1 -type d -execdir du -sh {} + to work thanks - if you post as an answer - I would accept it – the_velour_fog Nov 15 '15 at 06:47
  • you didn't use my ideas. i never suggested you do anything like that. what was wrong with -parg '*/*/*/*'? but you can post an answer, too, you know. – mikeserv Nov 15 '15 at 06:49

1 Answers1

5

find | xargs should always be used in conjunction with -print0 and -0, as explained in man find:

   -print0
          True; print the full file name on the standard output, followed
          by a null character (instead of the newline character that
          -print uses).  This allows file names that contain newlines or
          other types of white space to be correctly interpreted by
          programs that process the find output.  This option corresponds
          to the -0 option of xargs.

Thus you want:
find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 du -sh
or without find and with a sufficiently evolved shell (zsh):
print -N *(/) | xargs -0 du -sh
leading you to the even simpler:
du -sh *(/)

Michaël
  • 774