A powerful shell script that exports WordPress posts, custom permalinks, 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, and more
- 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
- 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
- Domain-Named Folders: Export folders include the domain name for easy identification
- Host Detection: Recognizes common hosts (Pressable, WP Engine, Kinsta) and adapts accordingly
./export_wp_posts.sh./export_wp_posts.sh --remote
# or
./export_wp_posts.sh -r./export_wp_posts.sh
./enable_excel.shThe script will:
- Auto-detect available SSH hosts from your ~/.ssh/config(remote mode)
- Suggest appropriate WordPress paths based on the host type
- 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_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=1)
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)
- Column I: Clickable WP Admin edit links
- 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
- SiteGround: Suggests ~/public_html
- Generic hosts: Default to ~/public_html
- ID: Post ID
- post_title: Title (sanitized, commas removed)
- post_name: URL slug
- custom_permalink: Custom permalink if set
- post_date: Publication date
- post_status: Status (publish, draft, etc.)
- post_type: Type (post, page, custom types)
- 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)
- For Pressable hosts, the script automatically uses -Tflag to disable pseudo-terminal
- Connection keepalive is enabled with 5-second intervals
- Large exports may cause connections to close - this is normal and handled gracefully
- 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
To enable detailed logging, edit the script and set:
DEBUG=1cd /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? nThe 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 script
- Incrementally add domains to the configuration file as they're used
- Present previously used domains as options when script is rerun
- Save SSH favorites from recently used connections
- Include 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 data
- Option 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
