Title: recurse_dirsize
Published: April 25, 2014
Last modified: February 24, 2026

---

# recurse_dirsize( string $directory, string|string[] $exclude = null, int $max_execution_time = null, array $directory_cache = null ): int|false|null

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#description)
 * [Parameters](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#source)
 * [Hooks](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#hooks)
 * [Related](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#wp--skip-link--target)

Gets the size of a directory recursively.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#description)󠁿

Used by [get_dirsize()](https://developer.wordpress.org/reference/functions/get_dirsize/)
to get a directory size when it contains other directories.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#parameters)󠁿

 `$directory`stringrequired

Full path of a directory.

`$exclude`string|string[]optional

Full path of a subdirectory to exclude from the total, or array of paths. Expected
without trailing slash(es).

Default:`null`

`$max_execution_time`intoptional

Maximum time to run before giving up. In seconds.
 The timeout is global and is 
measured from the moment WordPress started to load. Defaults to the value of `max_execution_time`
PHP setting.

Default:`null`

`$directory_cache`arrayoptional

Array of cached directory paths.
 Defaults to the value of `dirsize_cache` transient.

Default:`null`

## 󠀁[Return](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#return)󠁿

 int|false|null Size in bytes if a valid directory. False if not. Null if timeout.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#source)󠁿

    ```php
    function recurse_dirsize( $directory, $exclude = null, $max_execution_time = null, &$directory_cache = null ) {
    	$directory  = untrailingslashit( $directory );
    	$save_cache = false;

    	if ( ! isset( $directory_cache ) ) {
    		$directory_cache = get_transient( 'dirsize_cache' );
    		$save_cache      = true;
    	}

    	if ( isset( $directory_cache[ $directory ] ) && is_int( $directory_cache[ $directory ] ) ) {
    		return $directory_cache[ $directory ];
    	}

    	if ( ! file_exists( $directory ) || ! is_dir( $directory ) || ! is_readable( $directory ) ) {
    		return false;
    	}

    	if (
    		( is_string( $exclude ) && $directory === $exclude ) ||
    		( is_array( $exclude ) && in_array( $directory, $exclude, true ) )
    	) {
    		return false;
    	}

    	if ( null === $max_execution_time ) {
    		// Keep the previous behavior but attempt to prevent fatal errors from timeout if possible.
    		if ( function_exists( 'ini_get' ) ) {
    			$max_execution_time = ini_get( 'max_execution_time' );
    		} else {
    			// Disable...
    			$max_execution_time = 0;
    		}

    		// Leave 1 second "buffer" for other operations if $max_execution_time has reasonable value.
    		if ( $max_execution_time > 10 ) {
    			$max_execution_time -= 1;
    		}
    	}

    	/**
    	 * Filters the amount of storage space used by one directory and all its children, in megabytes.
    	 *
    	 * Return the actual used space to short-circuit the recursive PHP file size calculation
    	 * and use something else, like a CDN API or native operating system tools for better performance.
    	 *
    	 * @since 5.6.0
    	 *
    	 * @param int|false            $space_used         The amount of used space, in bytes. Default false.
    	 * @param string               $directory          Full path of a directory.
    	 * @param string|string[]|null $exclude            Full path of a subdirectory to exclude from the total,
    	 *                                                 or array of paths.
    	 * @param int                  $max_execution_time Maximum time to run before giving up. In seconds.
    	 * @param array                $directory_cache    Array of cached directory paths.
    	 */
    	$size = apply_filters( 'pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache );

    	if ( false === $size ) {
    		$size = 0;

    		$handle = opendir( $directory );
    		if ( $handle ) {
    			while ( ( $file = readdir( $handle ) ) !== false ) {
    				$path = $directory . '/' . $file;
    				if ( '.' !== $file && '..' !== $file ) {
    					if ( is_file( $path ) ) {
    						$size += filesize( $path );
    					} elseif ( is_dir( $path ) ) {
    						$handlesize = recurse_dirsize( $path, $exclude, $max_execution_time, $directory_cache );
    						if ( $handlesize > 0 ) {
    							$size += $handlesize;
    						}
    					}

    					if ( $max_execution_time > 0 &&
    						( microtime( true ) - WP_START_TIMESTAMP ) > $max_execution_time
    					) {
    						// Time exceeded. Give up instead of risking a fatal timeout.
    						$size = null;
    						break;
    					}
    				}
    			}
    			closedir( $handle );
    		}
    	}

    	if ( ! is_array( $directory_cache ) ) {
    		$directory_cache = array();
    	}

    	$directory_cache[ $directory ] = $size;

    	// Only write the transient on the top level call and not on recursive calls.
    	if ( $save_cache ) {
    		$expiration = ( wp_using_ext_object_cache() ) ? 0 : 10 * YEAR_IN_SECONDS;
    		set_transient( 'dirsize_cache', $directory_cache, $expiration );
    	}

    	return $size;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/functions.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/functions.php#L8763)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/functions.php#L8763-L8862)

## 󠀁[Hooks](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#hooks)󠁿

 [apply_filters( ‘pre_recurse_dirsize’, int|false $space_used, string $directory, string|string[]|null $exclude, int $max_execution_time, array $directory_cache )](https://developer.wordpress.org/reference/hooks/pre_recurse_dirsize/)

Filters the amount of storage space used by one directory and all its children, 
in megabytes.

## 󠀁[Related](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#related)󠁿

| Uses | Description | 
| [untrailingslashit()](https://developer.wordpress.org/reference/functions/untrailingslashit/)`wp-includes/formatting.php` |

Removes trailing forward slashes and backslashes if they exist.

  | 
| [wp_using_ext_object_cache()](https://developer.wordpress.org/reference/functions/wp_using_ext_object_cache/)`wp-includes/load.php` |

Toggles `$_wp_using_ext_object_cache` on and off without directly touching global.

  | 
| [get_transient()](https://developer.wordpress.org/reference/functions/get_transient/)`wp-includes/option.php` |

Retrieves the value of a transient.

  | 
| [set_transient()](https://developer.wordpress.org/reference/functions/set_transient/)`wp-includes/option.php` |

Sets/updates the value of a transient.

  | 
| [recurse_dirsize()](https://developer.wordpress.org/reference/functions/recurse_dirsize/)`wp-includes/functions.php` |

Gets the size of a directory recursively.

  | 
| [apply_filters()](https://developer.wordpress.org/reference/functions/apply_filters/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to a filter hook.

  |

[Show 1 more](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#)

| Used by | Description | 
| [WP_Debug_Data::get_sizes()](https://developer.wordpress.org/reference/classes/wp_debug_data/get_sizes/)`wp-admin/includes/class-wp-debug-data.php` |

Fetches the sizes of the WordPress directories: `wordpress` (ABSPATH), `plugins`, `themes`, and `uploads`.

  | 
| [get_dirsize()](https://developer.wordpress.org/reference/functions/get_dirsize/)`wp-includes/functions.php` |

Gets the size of a directory.

  | 
| [recurse_dirsize()](https://developer.wordpress.org/reference/functions/recurse_dirsize/)`wp-includes/functions.php` |

Gets the size of a directory recursively.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/recurse_dirsize/?output_format=md#changelog)󠁿

| Version | Description | 
| [MU (3.0.0)](https://developer.wordpress.org/reference/since/mu.3.0.0/) | MU (3.0.0) | 
| [5.6.0](https://developer.wordpress.org/reference/since/5.6.0/) | The `$directory_cache` parameter was added. | 
| [5.2.0](https://developer.wordpress.org/reference/since/5.2.0/) | The `$max_execution_time` parameter was added. | 
| [4.3.0](https://developer.wordpress.org/reference/since/4.3.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Frecurse_dirsize%2F)
before being able to contribute a note or feedback.