This script helps you migrate your Mac user's home directory to an external drive, with the option to use APFS encryption for data protection. Unlike full FileVault encryption, this method only encrypts user data rather than the entire system disk, making it suitable for users who want to separate their user data from the system.
This project was inspired by Will Haley's article, but has been simplified and improved for better stability and ease of use.
Please backup all important data before proceeding!
This process involves modifying critical system configurations, which if done incorrectly could result in inability to log in or data loss. It is strongly recommended that you:
- Make a complete backup of your system and data before starting
- Create an additional administrator account as a backup login method
- Ensure you understand how to use Recovery Mode in case emergency repairs are needed
- macOS 10.15 (Catalina) or later
- An external hard drive or SSD (SSD recommended for better performance)
- Administrator privileges
- Create an additional administrator account (strongly recommended)
- Log out of your current account and log in with the newly created administrator account
- Ensure the external drive is connected and recognized
Download the transfer.sh script and modify the following variables according to your situation:
CURRENT_USER="your_username" # Your username
INTERNAL_HOME="/Users/$CURRENT_USER" # Internal Home folder path
EXTERNAL_SSD="/Volumes/YourDisk" # External SSD mount point (replace with your SSD name)
EXTERNAL_HOME="$EXTERNAL_SSD/$CURRENT_USER" # New Home folder pathThen execute the script:
sudo bash transfer.shThe script will perform the following operations:
- Check if the external SSD is mounted
- Use rsync to copy the Home folder to the external SSD
- Fix permissions on the target folder
- Update the user's Home directory path
- Verify the update results
After completion, restart your Mac and try logging in with your original account. If everything is working correctly, your home directory should now be located on the external drive.
- Error Handling: The script continues execution even if some files cannot be copied
- Skip Existing Files: Files that already exist at the destination with the same or newer version will not be overwritten
- Detailed Logging: All operations are logged to a log file for troubleshooting
#!/bin/bash
set -u # Exit on undefined variable
# Define variables (adjust according to your situation)
CURRENT_USER="your_username" # Your username
INTERNAL_HOME="/Users/$CURRENT_USER" # Internal Home folder path
EXTERNAL_SSD="/Volumes/YourDisk" # External SSD mount point (replace with your SSD name)
EXTERNAL_HOME="$EXTERNAL_SSD/$CURRENT_USER" # New Home folder path
# Log file
LOG="/tmp/migrate_home.log"
# Check if external SSD is mounted
if [ ! -d "$EXTERNAL_SSD" ]; then
echo "Error: External SSD not mounted at $EXTERNAL_SSD. Please mount it first." | tee -a $LOG
exit 1
fi
# Start migration
echo "Migration started at $(date)" | tee -a $LOG
# Copy Home folder to external SSD
echo "Copying Home folder from $INTERNAL_HOME to $EXTERNAL_HOME..." | tee -a $LOG
sudo rsync -avh --progress --ignore-errors --update "$INTERNAL_HOME/" "$EXTERNAL_HOME/" >> $LOG 2>&1
RSYNC_EXIT_CODE=$?
# Check if rsync encountered errors, but don't exit the script
if [ $RSYNC_EXIT_CODE -ne 0 ]; then
echo "Warning: Some files could not be transferred during rsync operation (code $RSYNC_EXIT_CODE). Continuing anyway..." | tee -a $LOG
fi
# Fix permissions on target folder
echo "Fixing permissions on $EXTERNAL_HOME..." | tee -a $LOG
sudo chown -R "$CURRENT_USER:staff" "$EXTERNAL_HOME" >> $LOG 2>&1
# Update user Home directory path
echo "Updating Home directory path for user $CURRENT_USER..." | tee -a $LOG
sudo dscl . -change /Users/"$CURRENT_USER" NFSHomeDirectory "$INTERNAL_HOME" "$EXTERNAL_HOME" >> $LOG 2>&1
# Verify update results
NEW_HOME=$(dscl . -read /Users/"$CURRENT_USER" NFSHomeDirectory | awk '{print $2}')
if [ "$NEW_HOME" != "$EXTERNAL_HOME" ]; then
echo "Error: Failed to update Home directory path. Current path: $NEW_HOME" | tee -a $LOG
exit 1
else
echo "Home directory successfully updated to $EXTERNAL_HOME" | tee -a $LOG
fi
# Migration complete
echo "Migration finished at $(date)" | tee -a $LOG
echo "Please restart your Mac to apply changes. After verifying everything works, you can manually delete $INTERNAL_HOME if desired." | tee -a $LOGIf you want to encrypt your external drive, you can format it as "APFS (Encrypted)" using Disk Utility before migration. This way, your data will be password-protected.
If you want to use a USB key to automatically unlock the encrypted volume, you can refer to the relevant sections in Will Haley's detailed guide. This requires additional configuration:
- Create a key file and store it on a USB drive
- Create a startup script to automatically mount the encrypted volume
- Configure a LaunchDaemon to run the script at startup
Note: In macOS Catalina and later versions, the USB key auto-unlock feature may be unreliable due to security restrictions.
If you cannot log into your account after migration:
- Log in using the backup administrator account
- Check if the external drive is properly connected and mounted
- Check the log file at
/tmp/migrate_home.logfor error messages - If necessary, you can restore the original Home directory path using:
sudo dscl . -change /Users/your_username NFSHomeDirectory /Volumes/YourDisk/your_username /Users/your_username
If you encounter permission issues, try fixing permissions:
sudo chown -R your_username:staff /Volumes/YourDisk/your_usernameIf the external drive doesn't automatically mount at startup, you can add it to the Login Items in the Users & Groups section of System Preferences.
| Feature | This Solution | FileVault |
|---|---|---|
| Encryption Scope | User data only | Entire system disk |
| Performance Impact | Lower | Higher |
| Setup Complexity | More complex | Simple |
| Recovery Options | Fewer | Built-in recovery mechanisms |
| Use Case | Data-system separation | Complete system protection |
Bug reports and improvement suggestions are welcome! If you find any bugs or have suggestions for improvements, please submit an issue or pull request on GitHub.
This project is licensed under the MIT License - see the LICENSE file for details
- Will Haley for the original idea and detailed guide
- All users who tested and provided feedback