views:

420

answers:

6

I have some files across several folders:

/home/d/folder1/a.txt
/home/d/folder1/b.txt
/home/d/folder1/c.mov
/home/d/folder2/a.txt
/home/d/folder2/d.mov
/home/d/folder2/folder3/f.txt

How can I measure the grand total amount of disk space taken up by all the .txt files in /home/d/?

I know du will give me the total space of a given folder, and ls -l will give me the total space of individual files, but what if I want to add up all the txt files and just look at the space taken by all .txt files in one giant total for all .txt in /home/d/ including both folder1 and folder2 and their subfolders like folder3?

+6  A: 

find folder1 folder2 -iname '*.txt' -print0 | du --files0-from - -c -s | tail -1

Barry Kelly
du doesnt appear to have a --files-from option
ennuikiller
I meant a --files0-from option
ennuikiller
`du --versiondu (GNU coreutils) 5.93` - works on my machine.
Barry Kelly
And on my Cygwin install: du --versiondu (GNU coreutils) 6.10
Barry Kelly
on my linux box I'm running coreutils 4.5.3 so it's a bit outdated
ennuikiller
Of course, if compatibility with POSIX were required, then this wouldn't apply. But my (limited) experience with non-GNU userland has indicated that life's pretty harsh out there, best stick with GNU.
Barry Kelly
HP-UX Release 11i: November 2000... Ya, I don't have several of those options you used. Otherwise it is a nice one line solution, just not going to work for me.
Dan
+1  A: 

this will do it:

total=0
for file in $(ls *.txt)
do
space=$(ls -l $file | awk '{print $5}')
let total+=space
done
echo $total
ennuikiller
Will that find the files in subfolders folder1 and folder2?
Vinko Vrsalovic
Used a slight variation. Removed the first -l in ls. This still doesn't do any recursion, and it'll bomb on anything with spaces, but it is the closest thing I have. Thanks
Dan
no problem....I missed the subfolder requirement but thats easily handled by changing the for command to somethng like find . -name *.txt -exec ls {} ;\
ennuikiller
that ls *.txt in the for loop is redundant. just use shell expansion. --> for file in *.txt
ghostdog74
+2  A: 

Here's a way to do it, avoiding bad practice:

total=0
while read line
do
    size=($line)
    (( total+=size ))
done < <( find . -iname "*.txt" -exec du -b {} + )
echo $total

If you want to exclude the current directory, use -mindepth 2 with find.

Another version which may be more POSIX compliant:

find . -iname "*.txt" -exec du -b {} + | awk '{total += $1} END {print total}'
Dennis Williamson
A: 

use the tool du and the parameter -I to exclude all other files.

ppuschmann
A: 

GNU find,

find /home/d -type f -name "*.txt" -printf "%s\n" | awk '{s+=$0}END{print "total: "s" bytes"}'
ghostdog74
+1  A: 

Building on ennuikiller's, this will handle spaces in names. I needed to do this and get a little report:

find -type f -name "*.wav" | grep export | ./calc_space

#!/bin/bash
# calc_space
echo SPACE USED IN MEGABYTES
echo
total=0
while read FILE
do
    du -m "$FILE"
    space=$(du -m "$FILE"| awk '{print $1}')
    let total+=space
done
echo $total
John Minkle