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.sh
The 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.sh
This will install openpyxl in your user directory without affecting system Python.
The script recognizes and adapts to:
- Pressable: Auto-suggests
/htdocs
path - 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
-T
flag 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.sh
to 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=1
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
The 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