75

The Windows dir directory listing command has a line at the end showing the total amount of space taken up by the files listed. For example, dir *.exe shows all the .exe files in the current directory, their sizes, and the sum total of their sizes. I'd love to have similar functionality with my dir alias in bash, but I'm not sure exactly how to go about it.

Currently, I have alias dir='ls -FaGl' in my .bash_profile, showing

drwxr-x---+  24 mattdmo  4096 Mar 14 16:35 ./
drwxr-x--x. 256 root    12288 Apr  8 21:29 ../
-rw-------    1 mattdmo 13795 Apr  4 17:52 .bash_history
-rw-r--r--    1 mattdmo    18 May 10  2012 .bash_logout
-rw-r--r--    1 mattdmo   395 Dec  9 17:33 .bash_profile
-rw-r--r--    1 mattdmo   176 May 10  2012 .bash_profile~
-rw-r--r--    1 mattdmo   411 Dec  9 17:33 .bashrc
-rw-r--r--    1 mattdmo   124 May 10  2012 .bashrc~
drwx------    2 mattdmo  4096 Mar 24 20:03 bin/
drwxrwxr-x    2 mattdmo  4096 Mar 11 16:29 download/

for example. Taking the answers from this question:

dir | awk '{ total += $4 }; END { print total }'

which gives me the total, but doesn't print the directory listing itself. Is there a way to alter this into a one-liner or shell script so I can pass any ls arguments I want to dir and get a full listing plus sum total? For example, I'd like to run dir -R *.jpg *.tif to get the listing and total size of those file types in all subdirectories. Ideally, it would be great if I could get the size of each subdirectory, but this isn't essential.

  • 5
    Why does't ls -lh help you ? It prints total sum in top. You can also run du -sh *.exe to get disk space usage information in human readable form. – bagavadhar Apr 16 '13 at 19:40
  • @ashwin I don't know what the 'total' ls -lh is printing, but it's not always related to what the awk scripts below calculate, or what I add up by hand. Sometimes it's close to the number of KB of files in the directory, but it doesn't seem to take the allocated sizes of subdirectories into effect. I'd be grateful if you could point me toward an explanation of what exactly that number is... – MattDMo Apr 17 '13 at 17:05
  • see if my answer below works for you – bagavadhar Apr 17 '13 at 20:17
  • 1
    ls -lh does not show the total of size of a dir calculating it's contents – aequalsb Feb 9 '17 at 14:35

10 Answers 10

24

The following function does most of what you're asking for:

dir () { ls -FaGl "${@}" | awk '{ total += $4; print }; END { print total }'; }

... but it won't give you what you're asking for from dir -R *.jpg *.tif, because that's not how ls -R works. You might want to play around with the find utility for that.

  • 1
    This is true, if you're looking for essentially the contents size of each file, NOT the size the file consumes on disk. This distinction is more pronounced for very small files. On my distro's each file is allocated space on disk in 4 KB chunks (so a 300 byte file still uses 4K on a disk, as reported by the du command). Given that's what the OP was looking for "how much space each file takes up", then du is the way to do it. – Jon V Jan 10 '17 at 20:20
  • 1
    dir is already the name of a popular GNU coreutil, I'd rather not name a function like that. – dessert Nov 3 '17 at 8:18
  • Please fix so it works on both Linux and OS-S and your "-a" include "." and "..", which is not good : ) Here's the fixed command: dir () { ls -FAl "${@}" | awk '{ total += $5; print }; END { print "total:"total }'; } – Dmitry Shevkoplyas Sep 11 at 14:39
152

There's already a UNIX command for this: du

Just do:

du -ach 

As per convention you can add one or more file or directory paths at the end of the command. -h is an extension to convert the size into a human-friendly format, -a gives you the "apparent" size (file size instead of disk usage), and -c gives a total at the end.

  • 12
    Yes, du works fine. You can use the -c option (same as --total) to get a total at the end of the list. – MikeB May 21 '14 at 16:28
  • 6
    Note that du gives the disk usage, not the sum of file sizes. – Stéphane Chazelas Feb 9 '15 at 10:41
  • 7
    du -h doesn't sum the sizes of the files passed to it. du -h *.so shows the size of each file, but not the sum. I think what you're wanting here is du -hc *.so (or even du -hc *.so | tail -1). But of course, he wants the directory listing, too. – Limited Atonement Jan 15 '16 at 17:10
  • 1
    This command works only with short list of files. See what happens when you have 850000 files in a directory!!! – Hamid FzM May 20 '16 at 10:07
  • 3
    ! -a means --all. Consider rather using --apparent-size – Arnauld VM Nov 9 '18 at 13:31
19

You can use du -h -c directory|tail -1

This will generate a single line with memory usage.

  • 17
    du -hs directory if you only want the total. – Stéphane Chazelas Feb 9 '15 at 10:41
8

Simply print the current line that you are summing the total of:

dir | awk '{ print; total += $4 }; END { print "total size: ",total }'
6

with perl:

perl -le 'map { $sum += -s } @ARGV; print $sum' -- *.pdf

Size of all non-hidden PDF files in current directory.

1

Adding the following to .bash_profile or .bashrc works for me.

dir ()
{
find . -iname "$@" -exec ls -lh {} \;
find . -iname "$@" -print0|xargs -r0 du -csh|tail -n 1;
}

Now when i do a dir *.mp3 it does recursively and prints total at the end. You can control how much depth you want by adding a maxdepth parameter to the find. I know running find twice is not a very effiecnt idea. But i couldnt think of a better way. Atleast it gets the job done.

1

Using du and a awk statement like the one mentioned above will provide what you are looking for.

Example: du /home/abc/Downloads/*.jpg | awk '{ print; total += $1 }; END { print "total size: ",total }'

This will list all files in folder Downloads of user abc ending in .jpg and prints the sum of all these files at the end of the listing.

0

To get both, dir output and size calculation, without using any of the other proposed options, you can use tee(1) and process substitution...

dir | tee >( awk '{ total += $4 }; END { print total }' )
  • No need for tee, just dir | awk '{print; total += $4}; END {print total}' – Stéphane Chazelas Feb 9 '15 at 13:27
0
du path_to_your_files/*.jpg | awk '{ total += $1 }; END { print total }'
  • 3
    No. First, just giving a command is not an answer. Second, if you'd bothered to read the whole question, the other answers, and my comments, you'd have seen this is NOT what I want. – MattDMo Aug 26 '15 at 18:36
  • To be fair to the poster, this is the first search result for the Google search linux sum human readable sizes and is what I'm looking for. – Sridhar Sarnobat Aug 18 at 7:25
-2
du * | awk -v sum=0 '{print sum+=$1}' | tail -1
  • This doesn't do what I was asking for. – MattDMo Jun 3 '15 at 21:24

protected by Michael Mrozek Aug 26 '15 at 19:15

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.