# Change the Status of Many Posts at Once (WP-CLI)

> Adds a "wp change-status" command that moves posts from one status to another, for example every draft older than a date back to pending, with a preview count before anything changes.

- Type: PHP
- Runs: Run everywhere
- Category: [Developer](https://wpide.com/library/category/developer/)
- Tags: wp-cli, post-status, bulk
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/cli-change-post-status/

## Code

```php
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
    return;
}

WP_CLI::add_command( 'change-status', function ( $args, $assoc_args ) {
    $from     = sanitize_key( $assoc_args['from'] );
    $to       = sanitize_key( $assoc_args['to'] );
    $statuses = get_post_stati();

    if ( ! isset( $statuses[ $from ], $statuses[ $to ] ) ) {
        WP_CLI::error( 'Unknown post status.' );
    }

    $query_args = array(
        'post_type'      => sanitize_key( $assoc_args['post_type'] ?? 'post' ),
        'post_status'    => $from,
        'posts_per_page' => -1,
        'fields'         => 'ids',
        'no_found_rows'  => true,
    );
    if ( ! empty( $assoc_args['before'] ) ) {
        $query_args['date_query'] = array( array( 'before' => sanitize_text_field( $assoc_args['before'] ) ) );
    }

    $ids = get_posts( $query_args );

    if ( empty( $assoc_args['yes'] ) ) {
        WP_CLI::log( sprintf( '%d posts would change from %s to %s. Add --yes to apply.', count( $ids ), $from, $to ) );
        return;
    }

    foreach ( $ids as $id ) {
        wp_update_post( array( 'ID' => $id, 'post_status' => $to ) );
    }

    WP_CLI::success( sprintf( 'Changed %d posts from %s to %s.', count( $ids ), $from, $to ) );
}, array(
    'shortdesc' => 'Moves posts from one status to another.',
    'synopsis'  => array(
        array( 'type' => 'assoc', 'name' => 'from', 'description' => 'Current status, for example draft.' ),
        array( 'type' => 'assoc', 'name' => 'to', 'description' => 'New status, for example pending.' ),
        array( 'type' => 'assoc', 'name' => 'post_type', 'optional' => true, 'default' => 'post' ),
        array( 'type' => 'assoc', 'name' => 'before', 'optional' => true, 'description' => 'Only posts dated before this date (Y-m-d).' ),
        array( 'type' => 'flag', 'name' => 'yes', 'optional' => true ),
    ),
) );
```

## Notes

Example "wp change-status --from=draft --to=pending --before=2024-01-01 --yes"; without --yes it only counts.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Change the Status of Many Posts at Once (WP-CLI)" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
