OK, so here’s the scenario: I have 10 years of photographs I want to publish on my site which ends up being hundreds of posts and thousands of attachments. So what’s the easiest way of doing it?

I decided to implement some PowerShell magic & WP-CLI (WordPress command line interface). Hopefully you’re familiar with PowerShell already, click here if you want to learn about WP-CLI.

My plan:

  1. Copy media files to web server.
  2. Generate list of required posts.
  3. Generate post creation script.
  4. Create posts.
  5. Import media files into WordPress.
  6. Create gallery code for posts.
  7. Set the featured image.

Copy media files to web server.

When I created my Docker container for WordPress, I included a volume that mapped to a folder on my server that contained all my photos. I organized them in the same format WordPress would by creating folders for the year and month (2007/01).

Generate list of required posts.

I follow a pretty strict naming convention when it comes to my photos, so for each year/month folder that contained all of my photos, I was able to generate a list of unique galleries I would need.

If you need a tool to help you enumerate your files, I recommend you give AntRenamer a look.

My naming convention: DD-MM-YY-event-name_NUM.jpg

PowerShell script to grab all unique galleries:

$files = Get-ChildItem -Path "\\path\to\photo\folder\2007\01" 
$file = "C:\temp\tempdata.txt"
# this will strip off the last 8 characters and dump a unique list to a text file.
$files.Name -Replace ".{8}$" | Select-Object -Unique | Out-File -FilePath $file

Generate post creation script.

Once I have a list of unique galleries, I pretty up the data to put it in a CSV format with publish date, tags, category and excerpt.

CSV file content sample prior to running PowerShell script.

"YYYY-MM-DD","Post Title","Tags","Excerpt"

As you can see, there’s nothing fancy about the format, just needed it to play nice with PowerShell.

# data locations
$posts = Import-Csv "C:\temp\tempdata.txt" -Header Date,Title,Tags,Excerpt
$galfile = "c:\temp\galleryinfo.txt"

# loop through and generate post code
$posts | ForEach-Object {
    $date = $_.Date
    $title = $_.Title
    $tags = $_.Tags
    if ([string]::IsNullOrEmpty($_.Excerpt)) {
        $excerpt = $_.Title
    else {
        $excerpt = $_.Excerpt
    $gallery = "wp post create --post_date='$date 07:00:00' --post_excerpt='$excerpt' --post_title='$title' --tags_input='$tags' --post_author=1 --post_type=post --post_status=draft --allow-root --post_category=Gallery"
    $gallery | Out-File $galfile -Append

# code is copied to clipboard and temporary txt file is deleted
Get-Content $galfile | Set-Clipboard
Remove-Item $galfile -Force

Create posts.

Run the scripts generated in the previous step.

wp post create --post_date='YYYY-MM-DD 07:00:00' --post_excerpt='Excerpt' --post_title='Post Title' --tags_input='Tags' --post_author=1 --post_type=post --post_status=draft --allow-root --post_category=Gallery

Import media files into WordPress.

wp media import /var/www/html/wp-content/uploads/2007/01/*.jpg --preserve-filetime --skip-copy --allow-root

Create gallery code for posts.

This part generates the gallery code that you can paste right into the post. Otherwise, you’ll have to edit each post and manually create them

You’ll need to run this query against your WordPress database:

SELECT ID,GUID FROM wp_posts WHERE post_type='attachment' AND post_name like '01-10-07-yada%';

Sample output:

| 7501 | https://domain.com/01-10-07-yada-yada_001/ |

I know it seems complicated, but we need to massage the data a little bit more. Below is what I use which may not work for you out of the box. If your GUID resembles my sample which doesn’t include the image file extension, it should work. Otherwise, you’ll have to tweak the script.

$alt = "ALT tag for the images"
$urlrep = "https://domain.com/wp-content/uploads/2007/01/"
$data = (Get-Content "C:\temp\data.txt").Replace(' | ','","').Replace('| ','"').Replace(' |','"') | ConvertFrom-Csv -Header ID,URL

$firstline = "<ul class='wp-block-gallery columns-4 is-cropped'>"
$lastline = "</ul>"
$outputfile = "C:\temp\postinfo.txt"
New-Item $outputfile -Force | Out-Null
$firstline | Out-File $outputfile

$data | ForEach-Object {
    $id = $_.id
    $baseurl = $_.url -Replace "https://domain.com/","$urlrep" -Replace ".{1}$"
    $url = $baseurl + '.jpg'
    $datalink = $_.url
$content = "<li class=blocks-gallery-item><figure><a href='$url'><img src='$url' alt='$alt' data-id='$id' data-link='$datalink' class='wp-image-$id'></a></figure></li>"
$content | Out-File $outputfile -Append
$lastline | Out-File $outputfile -Append
(Get-Content $outputfile | Out-String) -replace "`r?`n(?!`r?`n)" | Set-Clipboard
Remove-Item $outputfile 

Set the post featured image.

While possible, I haven’t figured out how to automate this part yet…still doing it the old-school way.

What I would like to figure out.

Automate injecting gallery code and setting featured image when creating post.