Find and Delete Unused Tags and Categories (WP-CLI)
Adds a "wp empty-terms" command that lists the terms of a taxonomy that no post uses, and deletes them when you add --delete. The default category is always kept.
Opens WPIDE on
Code
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
return;
}
WP_CLI::add_command( 'empty-terms', function ( $args, $assoc_args ) {
$taxonomy = sanitize_key( $assoc_args['taxonomy'] ?? 'post_tag' );
if ( ! taxonomy_exists( $taxonomy ) ) {
WP_CLI::error( sprintf( 'Taxonomy "%s" does not exist.', $taxonomy ) );
}
// Recount first so the "count" column is trustworthy.
$all = get_terms( array( 'taxonomy' => $taxonomy, 'hide_empty' => false, 'fields' => 'tt_ids' ) );
wp_update_term_count_now( $all, $taxonomy );
$keep = 'category' === $taxonomy ? (int) get_option( 'default_category' ) : 0;
$terms = array_filter( get_terms( array( 'taxonomy' => $taxonomy, 'hide_empty' => false ) ), function ( $term ) use ( $keep ) {
return 0 === (int) $term->count && (int) $term->term_id !== $keep;
} );
if ( ! $terms ) {
WP_CLI::success( 'No unused terms.' );
return;
}
if ( empty( $assoc_args['delete'] ) ) {
WP_CLI\Utils\format_items( 'table', array_map( function ( $term ) {
return array( 'term_id' => $term->term_id, 'name' => $term->name, 'slug' => $term->slug );
}, $terms ), array( 'term_id', 'name', 'slug' ) );
WP_CLI::log( 'Add --delete to remove them.' );
return;
}
foreach ( $terms as $term ) {
wp_delete_term( $term->term_id, $taxonomy );
}
WP_CLI::success( sprintf( 'Deleted %d unused terms.', count( $terms ) ) );
}, array(
'shortdesc' => 'Lists or deletes terms with no posts.',
'synopsis' => array(
array( 'type' => 'assoc', 'name' => 'taxonomy', 'optional' => true, 'default' => 'post_tag' ),
array( 'type' => 'flag', 'name' => 'delete', 'optional' => true ),
),
) );
Notes
Example "wp empty-terms --taxonomy=post_tag --delete".
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.