A powerful shell script that exports WordPress posts, custom permalinks, custom meta fields, and users from WordPress sites - either locally or remotely via SSH. Generates both CSV and Excel files for SEO audits and data analysis.
- ✅ Proper CSV Handling: Correctly handles posts with commas, quotes, and special characters in titles
- 🔄 Unified Operation: Single script for both local and remote exports
- 📊 Excel Generation: Automatic conversion with clickable URLs and admin links
- 🔍 Dynamic Discovery: Automatically finds all public post types
- 🌐 Multi-Host Support: Works with Pressable, WP Engine, Kinsta, AWS, and more
- 🔧 SSH Debugging: Built-in verbose mode, pre-flight validation, and RemoteCommand detection
- 📋 Custom Meta Fields: Export any WordPress meta key as additional spreadsheet columns
- 💾 Configuration Memory: Remembers recent domains, SSH connections, and paths
- Unified Script: Single script handles both local and remote (SSH) exports
- Post Export: Exports all public post types (posts, pages, custom post types)
- Custom Permalinks: Captures custom permalink structures if set (always included)
- Custom Meta Fields: Export additional meta keys (e.g.,
_yoast_wpseo_title) as extra columns - User Export: Optional export of users with their post counts
- Excel Generation: Automatically converts CSV to Excel with formulas for clickable URLs
- SEO-Ready: Includes all necessary data for SEO audits and migration planning
- Smart SSH: Auto-detects SSH hosts from config and suggests appropriate paths
- Path Recall: Remembers previously used paths for each SSH host
- SSH Pre-Flight Validation: Tests connectivity, path existence, and WP-CLI availability before exporting
- RemoteCommand Detection: Automatically handles SSH configs with
RemoteCommandandRequestTTYdirectives - Sudo Wrapping: Detects
sudo -iu <user>patterns in SSH config and wraps commands accordingly - Domain-Named Folders: Export folders include the domain name for easy identification
- Host Detection: Recognizes common hosts and adapts accordingly
- Verbose/Debug Modes: CLI flags for troubleshooting SSH and export issues
# Local export (run from WordPress root directory)
./export_wp_posts.sh
# Remote export (via SSH)
./export_wp_posts.sh --remote
./export_wp_posts.sh -r
# Verbose mode (show SSH debug output)
./export_wp_posts.sh --verbose
./export_wp_posts.sh -v
# Debug mode (verbose + debug log file)
./export_wp_posts.sh --debug
# Combine flags
./export_wp_posts.sh --remote --verbose
./export_wp_posts.sh -r -v./enable_excel.shThe script will:
- Auto-detect available SSH hosts from your
~/.ssh/config(remote mode) - Show SSH favorites with saved paths from previous exports
- Suggest appropriate WordPress paths based on the host type or saved history
- Run pre-flight SSH validation (connectivity, path, WP-CLI)
- Discover all public post types dynamically
- Prompt for optional custom meta field exports
- Prompt for domain name and user export preference
- Generate all files locally in a timestamped, domain-named folder
All files are created in a timestamped folder that includes the domain name:
!export_wp_posts_20250811_143244_example-com/
├── export_all_posts.csv # Raw post export
├── export_custom_permalinks.csv # Custom permalink data
├── export_meta_[key].csv # Custom meta field data (one per key)
├── export_wp_posts_[timestamp].csv # Final merged CSV
├── export_wp_posts_[timestamp].xlsx # Excel file with formulas
├── export_users.csv # Raw user export (if enabled)
├── export_users_with_post_counts.csv # Users with post counts (if enabled)
└── export_debug_log.txt # Debug information (if --debug)
The generated Excel file includes:
- Row 1: Editable base domain (change this to update all URLs)
- Row 2: Column headers
- Column A: Formula-generated full URLs (uses custom permalink if exists, otherwise post_name)
- Custom Meta Columns: Inserted between custom_permalink and post_date (if any meta fields were exported)
- Last Column: Clickable WP Admin edit links
The number of columns adjusts dynamically based on how many custom meta fields are exported. The base is 7 columns (ID, title, name, custom_permalink, date, status, type) plus one column per meta field, plus the URL formula and edit link columns.
- Bash: Compatible shell environment
- For Local Mode:
- WP-CLI installed and accessible
- Run from WordPress root directory
- For Remote Mode:
- SSH access to the target server
- WP-CLI installed on the remote server
- For Excel Generation:
- Python 3
- openpyxl package (installed via
enable_excel.sh)
Run the included setup script:
./enable_excel.shThis will install openpyxl in your user directory without affecting system Python.
The script recognizes and adapts to:
- Pressable: Auto-suggests
/htdocspath - WP Engine: Auto-detects site path from hostname
- Kinsta: Suggests standard Kinsta paths
- AWS/EC2: Suggests
/var/www/html - AWS Lightsail / Bitnami: Suggests
/opt/bitnami/wordpress - Cloudways: Suggests
~/public_html - Flywheel: Suggests
~/public_html - SiteGround: Suggests
~/public_html - Generic hosts: Default to
~/public_html
If a host has been used before via SSH favorites, the previously used path is suggested instead.
The script stores configuration in .config/wp-export-config.json (gitignored) in the script directory:
- Recent Domains: Up to 10 recently exported domains, shown as selectable options
- SSH Favorites: Recently used SSH connections with their WordPress paths, shown at the top of the host list
- Export Statistics: Tracks export count, last export date, and post counts per domain
- Path Recall: When selecting an SSH host by number, if that host was previously used as a favorite, its saved path is suggested automatically
- ID: Post ID
- post_title: Title (sanitized, commas removed)
- post_name: URL slug
- custom_permalink: Custom permalink if set
- [Custom meta fields]: Any additional meta keys requested during export
- post_date: Publication date
- post_status: Status (publish, draft, etc.)
- post_type: Type (post, page, custom types)
When prompted, you can export any WordPress meta key as an additional column. Enter meta key names one at a time (press Enter on an empty line when done):
Export additional meta fields? (y/n, default: n): y
Enter meta key names one per line (press Enter twice when done):
Example: _custom_clean_url, _yoast_wpseo_title
> _yoast_wpseo_title
Added: _yoast_wpseo_title
> _custom_clean_url
Added: _custom_clean_url
>
Each meta field is exported to its own intermediate CSV, then merged into the final output. The custom_permalink column is always present regardless of custom meta field choices.
- ID: User ID
- user_login: Username
- user_email: Email address
- first_name: First name
- last_name: Last name
- display_name: Display name
- roles: User roles
- post_count: Number of posts authored (N/A for remote exports)
The script runs three validation tests before attempting an export:
- SSH Connectivity: Can we connect to the host?
- WordPress Path: Does the specified directory exist?
- WP-CLI: Is WP-CLI installed and accessible?
Each test provides specific troubleshooting guidance on failure.
Some SSH configs (e.g., AWS setups) include RemoteCommand or RequestTTY directives that prevent scripted command execution. The script:
- Detects
RemoteCommandviassh -G <host> - Overrides it with
-o RemoteCommand=none -o RequestTTY=no - If the RemoteCommand uses
sudo -iu <user>, wraps all WP-CLI commands with the same sudo prefix
This is fully automatic — no manual configuration needed.
# Show SSH stderr output for connection debugging
./export_wp_posts.sh --verbose
# Full debug mode (verbose + debug log file in export directory)
./export_wp_posts.sh --debug- The script uses
-Tflag to disable pseudo-terminal allocation - Connection keepalive is enabled with 5-second intervals
- SSH timeout set to 30 seconds
- If you see "Cannot execute command-line and remote command", the RemoteCommand detection should handle this automatically
- For manual debugging:
ssh -v <host> 'echo test'
- If Excel generation fails, ensure Python and openpyxl are installed
- Run
./enable_excel.shto set up Excel support - CSV files can always be imported into Excel/Google Sheets manually
cd /var/www/mysite
./export_wp_posts.sh
# Enter domain: mysite.com
# Include users? y./export_wp_posts.sh --remote
# Select host: 1 (pressable-site)
# Confirm path: /htdocs
# Enter domain: client-site.com
# Include users? n./export_wp_posts.sh -r -v
# Select host: my-aws-host
# Path: /var/www/blog/public_html/blog/
# Domain: example.com
# Export additional meta fields? y
# > _yoast_wpseo_title
# > _custom_clean_url
# >
# Include users? yThe original local-only script is preserved as export_wp_posts_legacy.sh for reference.
Feel free to submit issues and enhancement requests!
MIT License - see LICENSE file for details
Eric Rasch GitHub: https://github.com/ericrasch/script-export-wp-posts
Save settings the first time a user runs the scriptIncrementally add domains to the configuration file as they're usedPresent previously used domains as options when script is rerunSave SSH favorites from recently used connectionsInclude last exported date for each domain
- Add ability to save and reuse export configurations (e.g.,
--profile seo-audit) - Different profiles for different use cases (migration, audit, backup)
- Export only posts modified since last export
- Options like
--since "2025-08-01"or--since-last-export
- JSON export for programmatic processing
- SQL export for direct database dumps
- Markdown export for documentation
- Automatic retry on SSH connection failures
- Resume capability for interrupted exports
- Better timeout handling for large sites
- Check for broken internal links
- Identify missing featured images
- Find duplicate slugs/permalinks
- Generate summary reports with potential issues
- Export from multiple sites in one run
- Support for batch configuration files
Export specific custom fields/meta dataOption like--meta-keys "seo_title,seo_description"
- Parallel processing for large exports
- Compression of export files
- Option to exclude post content for faster exports
- Option to exclude specific post-types
- Webhook notifications on completion
- Direct upload to Google Drive/Dropbox
- Email export results
- Convert relative URLs to absolute
- Strip HTML from titles/content
- Normalize date formats
- Encrypted exports for sensitive data
- Audit log of exports
- Option to redact personal data
