Media Library Disk Usage by Type and Year (WP-CLI)
Adds a "wp media-usage" command that totals how much disk space uploads use, grouped by file type or by upload year, including every generated image size, to see what fills your hosting space.
Opens WPIDE on
Code
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
return;
}
WP_CLI::add_command( 'media-usage', function ( $args, $assoc_args ) {
$by = ( $assoc_args['by'] ?? 'type' ) === 'year' ? 'year' : 'type';
$totals = array();
$paged = 1;
do {
$ids = get_posts( array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'posts_per_page' => 500,
'paged' => $paged++,
'fields' => 'ids',
'no_found_rows' => true,
) );
foreach ( $ids as $id ) {
$file = get_attached_file( $id );
$bytes = $file && file_exists( $file ) ? filesize( $file ) : 0;
$meta = wp_get_attachment_metadata( $id );
foreach ( (array) ( $meta['sizes'] ?? array() ) as $size ) {
$path = $file ? path_join( dirname( $file ), $size['file'] ) : '';
$bytes += $path && file_exists( $path ) ? filesize( $path ) : 0;
}
if ( ! empty( $meta['original_image'] ) && $file ) {
$original = path_join( dirname( $file ), $meta['original_image'] );
$bytes += file_exists( $original ) ? filesize( $original ) : 0;
}
$group = 'year' === $by ? get_the_date( 'Y', $id ) : ( get_post_mime_type( $id ) ? get_post_mime_type( $id ) : 'unknown' );
$totals[ $group ]['files'] = ( $totals[ $group ]['files'] ?? 0 ) + 1;
$totals[ $group ]['bytes'] = ( $totals[ $group ]['bytes'] ?? 0 ) + $bytes;
}
} while ( count( $ids ) === 500 );
uasort( $totals, function ( $a, $b ) {
return $b['bytes'] <=> $a['bytes'];
} );
$rows = array();
foreach ( $totals as $group => $data ) {
$rows[] = array( $by => $group, 'files' => $data['files'], 'size' => size_format( $data['bytes'], 1 ) );
}
if ( ! $rows ) {
WP_CLI::success( 'The Media Library is empty.' );
return;
}
WP_CLI\Utils\format_items( $assoc_args['format'] ?? 'table', $rows, array( $by, 'files', 'size' ) );
}, array(
'shortdesc' => 'Shows Media Library disk usage grouped by type or year.',
'synopsis' => array(
array( 'type' => 'assoc', 'name' => 'by', 'optional' => true, 'default' => 'type', 'options' => array( 'type', 'year' ) ),
array( 'type' => 'assoc', 'name' => 'format', 'optional' => true, 'default' => 'table', 'options' => array( 'table', 'csv', 'json' ) ),
),
) );
Notes
Run "wp media-usage --by=year" or "--by=type" (default); it reads file sizes from disk, so large libraries take a moment.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.