Deleting thousands of posts in WordPress
John Mc By - John Mc

Deleting thousands of posts in WordPress

So you’ve been given the task of deleting thousands of posts in WordPress. As you start selecting all on page one and doing a bulk delete of the 30 items you start to think, “There must be a better way”. So you fiddle around in the screen options and select it to display 500 rows. Well that didn’t work, it just slowed everything down to a halt. “There must be a better way”…

I am here to tell you today that you’re in luck, there is a better way of deleting thousands of posts in WordPress. It’s really simple and quick. The caveat is that you have to get your hands a little dirty with the command line, specifically using WordPress command line tool, WP-CLI.

So, if you have access to the command line, 5 minutes and you need to delete thousands of WordPress posts, then read on!


Get a copy of WP-CLI using the really simple installation instructions on their home page. In this post I’m going to assume you’ve followed their guide on making wp-cli globally available.

Deleting thousands of WordPress Posts

To get a listing of posts with WP-CLI you use the post command with the list subcommand. You can then add parameters as you would for a regular WordPress query with its args.

For instance, if we were looking to delete all custom posts of type ‘movies’, and also to only output the post ID (because that’s what we’ll use to delete them soon), use the following command:

wp post list --post_type=movies --field=ID

Great, we’ve listed all of our movies. Now, to delete a post use the post command with the delete subcommand. For instance if one of our movie IDs was 123 then to delete post 123 use command:

wp post delete 123 --force

The –force flag forces the delete, rather than putting the posts into trash.

Now, let’s bring these two together. On Linux there is a command called xargs. Essentially with this command you can use the output from one command and iterrate over the second command with the output one at time. In otherwords, our wp post list command gave us thousands of post IDs. We pipe these to xargs with the wp post delete command and it will run each of these IDs through the delete command, one by one. This combined command to delete thousands of WordPress posts looks like this:

wp post list --post_type=entries --field=ID | xargs  wp post delete {} --force

Once done, you’ll have freed your database of the movies posts. You can pass any parameters you’d usually pass to WP Query to target which movies you want to delete.

The one remaining issue is that this will not (or at least, did not in my case) delete the media attachments (featured images). After deleting the posts you’ll notice that its media is listed as unattached. So, we can use basically the same commands as above, except this time our post_type will be ‘attachment’ and we’ll set post_parent=0 to target only unattached media. That command looks like this:

wp post list --post_type='attachment' --field=ID --post_parent=0 | xargs wp post delete {} --force

One caveat of this is that if someone uploaded an image through the media centre and then copied the URL and pasted that directly into a post’s body content then it would not have a parent ID and will be deleted. You’ll need to think very carefully about that.

So, now armed with this you can delete your entire WordPress site and make everyone not sleep for days. In other words, be careful… be very careful. Take full backups before running these commands. Once the data is gone, its gone for good.


1 Comment

To add on to this, I've also used this to delete thousands of wordpress users when cleaning up a staging site. That code looked something like this: wp user list --role=client --field=ID | xargs wp user delete {} --reassign=1 This lists all user IDs where the user is a custom user type of client and then passes those user IDs to the wordpress delete user function. It uses --reassign=1 to assign those user's posts to user 1. In this case they had no posts but we need this to allow the script to not block

7 months ago Reply

Leave a Comment

Your email address will not be published. Required fields are marked *