Is it possible to easily get the size of a folder on the SD card? I use a folder for caching of images, and would like to present the total size of all cached images. Is there a way to this other than iterating over each file? They all reside inside the same folder?
11 Answers
Just go through all files and sum the length of them:
/**
* Return the size of a directory in bytes
*/
private static long dirSize(File dir) {
if (dir.exists()) {
long result = 0;
File[] fileList = dir.listFiles();
if (fileList != null) {
for(int i = 0; i < fileList.length; i++) {
// Recursive call if it's a directory
if(fileList[i].isDirectory()) {
result += dirSize(fileList[i]);
} else {
// Sum the file size in bytes
result += fileList[i].length();
}
}
}
return result; // return the file size
}
return 0;
}
NOTE: Function written by hand so it could not compile!

- 6,002
- 1
- 35
- 40
-
You might want to replace findFile by dirSize :) – Maurits Rijk Oct 28 '10 at 08:23
-
i suggest to replace `dir.exists()` with `dir.isDirectory()`. if a file is given as argument NullPointerException is thrown due to listFiles() result. – tux_mind Dec 20 '13 at 17:14
-
@Moss The "for-each" loop is better, like Google suggest in http://developer.android.com/training/articles/perf-tips.html#Loops – Kevin Robatel Feb 23 '15 at 15:13
-
Check fileList ot being null before the loop on it – mehrdad seyrafi Jun 08 '17 at 02:55
Here's some code that avoids recursion:
public static long getFileSize(final File file) {
if (file == null || !file.exists())
return 0;
if (!file.isDirectory())
return file.length();
final List<File> dirs = new LinkedList<>();
dirs.add(file);
long result = 0;
while (!dirs.isEmpty()) {
final File dir = dirs.remove(0);
if (!dir.exists())
continue;
final File[] listFiles = dir.listFiles();
if (listFiles == null || listFiles.length == 0)
continue;
for (final File child : listFiles) {
// Note: if you want to get physical size and not just logical size, include directories too to the result, and not just normal files
if (child.isDirectory()) {
dirs.add(child);
} else {
result += child.length();
}
}
}
return result;
}

- 114,585
- 152
- 739
- 1,270
-
this is absolutely right answer for calculating size of FILE/FOLDER – Pir Fahim Shah May 08 '14 at 13:43
-
I was actually surprised to see that (on Android) each folder takes about 4KB even when it's empty. wonder why they did it this way. – android developer May 08 '14 at 15:07
-
@androiddeveloper It's the sector size. You'll notice that the same is true on any desktop OS. – You'reAGitForNotUsingGit Jul 10 '17 at 11:36
-
-
The value matches the details reported by Samsung My Files app on selected files in a folder – ecle May 18 '21 at 09:37
-
@androiddeveloper yes, the total size of every file in a folder (not including the folder, of course) – ecle May 19 '21 at 14:29
-
@ecle I see. I wonder: Does the built-in "My files" app of Samsung show anything about "Android" folder on Android 11 (which sadly restricts access to this folder for third party apps) ? Can it show the total size there? Can it show its content? – android developer May 20 '21 at 08:04
-
@androiddeveloper sorry, I don't have access to any Samsung device > Android 7.0+ to verify – ecle May 20 '21 at 08:18
-
-
This adds `length()` of directories to the sum as well. Is this right? According to docs, “The return value [of `length()`] is unspecified if this pathname denotes a directory.” – squirrel Oct 24 '22 at 15:11
-
@squirrel If you don't want it, have the check that it's a file, and only then accumulate – android developer Oct 24 '22 at 17:19
-
@androiddeveloper I don't think this is a question of what I want. Since the `length()` on a directory returns an unspecified value, I think it's an error to use it for directories at all? – squirrel Oct 25 '22 at 15:49
-
-
@androiddeveloper I guess what I am suggesting is to edit the answer. I take it from the text that this answer is in a way more correct since it “calculates the physical size instead of the logical size”, which is what `length()` seems to be responsible for as it's about the only difference to other answers that can affect the result. While in fact the result is undefined. – squirrel Oct 26 '22 at 14:35
-
@squirrel I've read somewhere that this is giving it as such result. If you don't trust it, change this code to how you see fit. – android developer Oct 27 '22 at 15:15
you should use this code:
public static long getFolderSize(File f) {
long size = 0;
if (f.isDirectory()) {
for (File file : f.listFiles()) {
size += getFolderSize(file);
}
} else {
size=f.length();
}
return size;
}

- 1,318
- 11
- 20

- 71
- 1
- 1
-
Great solution for me, I am having a folder with some audio files and it works perfekt for me! (I am having no subfolders in this folder!) – basti12354 Apr 04 '15 at 15:17
/**
* Try this one for better performance
* Mehran
* Return the size of a directory in bytes
**/
private static long dirSize(File dir) {
long result = 0;
Stack<File> dirlist= new Stack<File>();
dirlist.clear();
dirlist.push(dir);
while(!dirlist.isEmpty())
{
File dirCurrent = dirlist.pop();
File[] fileList = dirCurrent.listFiles();
for(File f: fileList){
if(f.isDirectory())
dirlist.push(f);
else
result += f.length();
}
}
return result;
}

- 39,597
- 13
- 90
- 111

- 61
- 1
- 1
-
2Since we're talking about file operations, the recursion is unlikely to account for much of the performance hit. Also, the java.util.Stack implementation is very slow. I tried to optimize a recursive algorithm with it and it was actually slower then to let the JVM do its job. – Kevin Coulombe Dec 12 '11 at 05:21
-
java.util.Stack class methods are synchronized. If you really want to avoid recursion it's better to use LinkedList. – Roman Mazur Feb 12 '13 at 14:06
The way of #Moss is right. This is my code for those who want to change bytes to human readable format. You just need to assign path of your folder to dirSize(String path)
and get human readable format based on byte, kilo, mega and etc.
private static String dirSize(String path) {
File dir = new File(path);
if(dir.exists()) {
long bytes = getFolderSize(dir);
if (bytes < 1024) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(1024));
String pre = ("KMGTPE").charAt(exp-1) + "";
return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
}
return "0";
}
public static long getFolderSize(File dir) {
if (dir.exists()) {
long result = 0;
File[] fileList = dir.listFiles();
for(int i = 0; i < fileList.length; i++) {
// Recursive call if it's a directory
if(fileList[i].isDirectory()) {
result += getFolderSize(fileList[i]);
} else {
// Sum the file size in bytes
result += fileList[i].length();
}
}
return result; // return the file size
}
return 0;
}

- 52,260
- 74
- 224
- 365
Problem with other solution is that they provide you only logical size of all files in specified directory. It will be different from actual (physical) used space. If your directory has a lot of subdirectories and/or small files, there may be a huge difference between logical and actual size of directory.
Here is what I found how to take in count physical structure of FS.
public static long getDirectorySize(File directory, long blockSize) {
File[] files = directory.listFiles();
if (files != null) {
// space used by directory itself
long size = file.length();
for (File file : files) {
if (file.isDirectory()) {
// space used by subdirectory
size += getDirectorySize(file, blockSize);
} else {
// file size need to rounded up to full block sizes
// (not a perfect function, it adds additional block to 0 sized files
// and file who perfectly fill their blocks)
size += (file.length() / blockSize + 1) * blockSize;
}
}
return size;
} else {
return 0;
}
}
You can use StatFs
to get block size:
public static long getDirectorySize(File directory) {
StatFs statFs = new StatFs(directory.getAbsolutePath());
long blockSize;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
blockSize = statFs.getBlockSizeLong()
} else {
blockSize = statFs.getBlockSize();
}
return getDirectorySize(directory, blockSize);
}

- 8,647
- 6
- 38
- 44
-
I've noticed that if I call "length()" on a directory, I don't get 0, but a real number. Is it possible that instead of using what you've done you can just use "length()" on the directories (and of course do the rest- adding the size of normal files) ? – android developer Apr 30 '14 at 22:10
-
Did you mean for `return getDirectorySize(directory, blockSize);` to just be `return blockSize`? – Joshua Pinter Oct 15 '19 at 03:57
-
Thank you so much for providing this answer. This was our first introduction to `StatFs` and was exactly what we needed. On large and complex directories, it was over 1000x faster than recursively getting the file size. Brilliant! – Joshua Pinter Oct 16 '19 at 20:41
You can query MediaStore for a directory size on internal storage. This is much faster than a recursive method getting the length of each file in a directory. You must have READ_EXTERNAL_STORAGE
permission granted.
Example:
/**
* Query the media store for a directory size
*
* @param context
* the application context
* @param file
* the directory on primary storage
* @return the size of the directory
*/
public static long getFolderSize(Context context, File file) {
File directory = readlink(file); // resolve symlinks to internal storage
String path = directory.getAbsolutePath();
Cursor cursor = null;
long size = 0;
try {
cursor = context.getContentResolver().query(MediaStore.Files.getContentUri("external"),
new String[]{MediaStore.MediaColumns.SIZE},
MediaStore.MediaColumns.DATA + " LIKE ?",
new String[]{path + "/%"},
null);
if (cursor != null && cursor.moveToFirst()) {
do {
size += cursor.getLong(0);
} while (cursor.moveToNext());
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return size;
}
/**
* Canonicalize by following all symlinks. Same as "readlink -f file".
*
* @param file
* a {@link File}
* @return The absolute canonical file
*/
public static File readlink(File file) {
File f;
try {
f = file.getCanonicalFile();
} catch (IOException e) {
return file;
}
if (f.getAbsolutePath().equals(file.getAbsolutePath())) {
return f;
}
return readlink(f);
}
Usage:
File DCIM = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
long directorySize = getFolderSize(context, DCIM);
String formattedSize = Formatter.formatFileSize(context, directorySize);
System.out.println(DCIM + " " + formattedSize);
Output:
/storage/emulated/0/DCIM 30.86 MB

- 8,146
- 7
- 57
- 139

- 37,824
- 19
- 133
- 148
-
-
`"/%/%"` - is wrong, it should be `/%` if you don't want to exclude files in root folder - `getFolderSize(context, folderRoot);`, with your solution `"/%/%"` it would get size only of subfolders in that root folder – user924 Dec 21 '20 at 14:12
-
@user924 please don't confuse people without references Media provider table containing an index of all files in the media storage, including non-media files. https://developer.android.com/reference/android/provider/MediaStore.Files – Cyber Avater Jun 26 '23 at 04:32
below method return you size of folder:-
public static long getFolderSize(File dir) {
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
// System.out.println(file.getName() + " " + file.length());
size += file.length();
} else
size += getFolderSize(file);
}
return size;
}
call above method :-
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/urfoldername/");
long folder_size=getFolderSize(file);
return you size of folder.

- 37,851
- 12
- 116
- 113
Hope this helps
import this
import android.text.format.Formatter;
For file size
public static String fileSize(File file, Context context) {
return Formatter.formatFileSize(context, file.length());
}
For folder size
public static String forlderSize(File file, Context context) {
long length = 0;
File[] folderFiles = file.listFiles();
for (File f : folderFiles) {
length += f.length();
}
return Formatter.formatFileSize(context, length);
}

- 71
- 1
- 2
Iterating through all files is less than 5 lines of code and the only reasonable way to do this. If you want to get ugly you could also run a system command (Runtime.getRuntime().exec("du");) and catch the output ;)

- 9,789
- 2
- 36
- 53
-
1Fair enough. Just figured it was such a common use case that there should be some native solution. Laziness is good ... Five lines later, and I'm happy :) – Gunnar Lium Oct 28 '10 at 08:38
-
In Clojure: (defn dir-size [dir] (reduce + (map #(.length %) (.listFiles (new File dir))))) – Maurits Rijk Oct 28 '10 at 12:19
-
1I don't think it's safe to rely on du being available and executable. – David Snabel-Caunt Mar 14 '11 at 11:04
-
How exactly does one fire the "du" command? I tried - `Runtime.getRuntime().exec("/system/bin/du -b -d1 "+dir.getCanonicalPath(), new String[]{}, Environment.getRootDirectory());` didnt work. Nor did - `(Runtime.getRuntime().exec("du"))` – Amey Jul 07 '11 at 19:53
Here's a snippet from Linh Toòng's answer with a couple more checks (mainly to stop Android Studio's warnings!)
private long getFolderSize(File file) {
if (file == null || !file.exists())
return 0;
long size = 0;
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files == null || files.length == 0)
return size;
for (File f : files)
size += getFolderSize(f);
} else
size += file.length();
return size;
}

- 663
- 3
- 7
- 24