Over at my subdomain hosting pictures of Girls’ Generation, I need to create a huge amount of new posts. Since the site is hosted on a UNIX machine (FreeBSD, to be specific), I can use wp-cli and make a simple Bash script. I’ve used wp-cli a lot over the past year, both for work and personal projects, so I thought I could write the script from scratch in 30 minutes flat. I couldn’t be more wrong…

Assuming you already have a WordPress site working in a UNIX environment, simply change your working directory to the webroot of the site. You can check out the help by typing wp help, or you can add more specific queries, like wp help post create.

The help page on how to create a new post seems straightforward enough:

wp post create /path/to/text-file-for-content --post_type=post --post_status=publish --post_title="Your Page Title Here" --post_category="yourcategoryhere" --tags_input="yourtagshere"

Except that there are several problems:

  • –post_category takes the ID of the category you want, and not the text.
  • It does not set the author of the post
  • And most importantly, it does not publish the actual post and only save it as a draft!

I managed to get around these issues, but not without a lot of head-scratchings, Googling around, and trials and errors. As for the issue with category, you have to note down all the category IDs in your site, then implement a switch-case, if-else, or some kind of loop so that the wp post create gets the ID and not the name. To get the category ID:

wp term list category

This is my own example of a switch case that sets the category ID according to the content the variable $POSTCATEGORYNAME, then the post command would use variable $POSTCATEGORYID:

#Set post category ID
case $POSTCATEGORYNAME in
        [Aa][Ll][Ll])
                POSTCATEGORYID=451;;
        [Hh][Yy][Oo][Yy][Eo][Oo][Nn])
                POSTCATEGORYID=244;;
        [Ss][Ee][Oo][Hh][Yy][Uu][Nn])
                POSTCATEGORYID=411;;
        [Ss][Oo][Oo][Yy][Oo][Uu][Nn][Gg])
                POSTCATEGORYID=303;;
        [Ss][Uu][Nn][Nn][Yy])
                POSTCATEGORYID=151;;
        [Tt][Aa][Ee][Tt][Ii][Ss][Ee][Oo])
                POSTCATEGORYID=579;;
        [Tt][Aa][Ee][Yy][Ee][Oo][Nn])
                POSTCATEGORYID=4;;
        [Tt][Ii][Ff][Ff][Aa][Nn][Yy])
                POSTCATEGORYID=177;;
        [Yy][Oo][Oo][Nn][Aa])
                POSTCATEGORYID=345;;
        [Yy][Uu][Rr][Ii])
                POSTCATEGORYID=271;;
esac

One problem solved. For the next problem, after reading the WordPress page about wp_insert_post(), I thought I could set the author just by adding –post_author=”authorname” to the same line and it would work, right? Wrong.

I need to create another line in order to set the author, and in order to do that, I need to get the ID of the new post. Now we’re going even deeper down the rabbit hole…

wp post create has an option named –porcelain that outputs the ID of new post to console. Now we can implement it in Bash by creating a variable to get the output, then set that variable as the post ID in the new line (assuming the author ID is 1, like in my case):

POSTID=$(wp post create /path/to/text-file-for-content --post_type=post --porcelain --post_status=publish --post_title="Your Page Title Here" --post_category="yourcategoryhere" --tags_input="yourtagshere")
wp post update $POSTID --post_author=1 --quiet

I added the option –quiet so it doesn’t output anything else. To see your user ID, type wp user list in your webroot.

Just one issue left. How to set the post as actually published is almost identical to the one above, just by replacing –post_author with –post_status, and remove –post_status from the main line because it doesn’t work anyway. To make it more flexible, we can set variables for the post title and tags. These three lines can solve the last two issues, with $POSTTITLE as post title, $POSTTAG as tags, and $POSTCATEGORYID as post category ID as explained above:

POSTID=$(wp post create /path/to/text-file-for-content --post_type=post --porcelain --post_title="$POSTTITLE" --post_category="$POSTCATEGORYID" --tags_input="$POSTTAG")
wp post update $POSTID --post_status=publish --quiet
wp post update $POSTID --post_author=1 --quiet

If you need to set more details about the post, especially the ones created by plugins, you can add wp post meta add $POSTID yourownoption yourvalue –quiet below. You can find out what options you can use by:

wp post meta list yourpostid

To find out what is your post ID, go to the site and try to edit a post. You should see ?post= in the address bar, and that is ID of the post you’re editing.

I hope this post actually helps someone trying to do this, and the wp-cli developers to know that the option –<field>=<value> really does nothing.

Leave a Reply

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