Btrfs to Ext4 Migration Automation Helper Script

# ==============================================================================

# Btrfs to Ext4 Migration Automation Helper Script

# ==============================================================================

# This script guides and automates the migration of a filesystem from Btrfs to Ext4.

# Because in-place conversion is not possible, this script automates the:

# 1. Backup phase (via rsync with preservation of all attributes)

# 2. Unmounting and formatting of the target partition to Ext4

# 3. Acquisition of the new UUID and generation of the /etc/fstab entry

# 4. Verification and mounting test of the new configuration

# 5. Restore phase (via rsync)

# WARNING: Formatting is destructive. Ensure your backups are complete and verified.

# ==============================================================================

set -euo pipefail

# ANSI color codes for readability

RED='\033[0;31m'

GREEN='\033[0;32m'

YELLOW='\033[1;33m'

BLUE='\033[0;34m'

NC='\033[0m' # No Color

log_info() {

echo -e "{NC} $1"

}

log_success() {

echo -e "{NC} $1"

}

log_warn() {

echo -e "{NC} $1"

}

log_error() {

echo -e "{NC} $1"

}

# ------------------------------------------------------------------------------

# 1. Root Check

# ------------------------------------------------------------------------------

if [ "$EUID" -ne 0 ]; then

log_error "This script must be run with root privileges (sudo)."

exit 1

fi

# ------------------------------------------------------------------------------

# 2. Interactive Input Gather & Validation

# ------------------------------------------------------------------------------

echo -e "{NC}"

echo "This helper will guide you through backing up, formatting, and restoring your data."

echo ""

# Get Source Mount

read -rp "Enter the current Btrfs mount path (e.g., /mnt/btrfs-source): " SOURCE_MOUNT

if [! -d "$SOURCE_MOUNT" ]; then

log_error "Source directory '$SOURCE_MOUNT' does not exist."

exit 1

fi

# Ensure trailing slash for rsync

RSYNC_SOURCE="${SOURCE_MOUNT%/}/"

# Get Backup Destination

read -rp "Enter the backup destination directory (e.g., /mnt/backup-destination): " BACKUP_DEST

if [! -d "$BACKUP_DEST" ]; then

log_warn "Backup directory '$BACKUP_DEST' does not exist. Attempting to create it..."

mkdir -p "$BACKUP_DEST"

fi

RSYNC_BACKUP="${BACKUP_DEST%/}/"

# Get Partition Block Device

read -rp "Enter the partition block device to be formatted (e.g., /dev/sdXN): " BLOCK_DEVICE

if [! -b "$BLOCK_DEVICE" ]; then

log_error "Block device '$BLOCK_DEVICE' does not exist or is not a block device."

exit 1

fi

# Confirm device details to prevent disastrous formatting of wrong drive

echo -e "\n{NC}"

lsblk "$BLOCK_DEVICE" || true

echo ""

read -rp "Are you absolutely sure '$BLOCK_DEVICE' is the correct partition to format? (type 'YES' to confirm): " CONFIRM_DEVICE

if [ "$CONFIRM_DEVICE"!= "YES" ]; then

log_error "Migration aborted by user."

exit 1

fi

# ------------------------------------------------------------------------------

# 3. Step 1: Backup Phase

# ------------------------------------------------------------------------------

echo -e "\n{NC}"

log_info "Running rsync to back up $RSYNC_SOURCE to $RSYNC_BACKUP"

log_info "Preserving ownership (numeric IDs), hard links, ACLs, and extended attributes..."

# Execute rsync with recommended flags

rsync -aHAXv --numeric-ids --progress "RSYNC_BACKUP"

log_success "Backup completed successfully."

# ------------------------------------------------------------------------------

# 4. Step 2: Unmount & Format

# ------------------------------------------------------------------------------

echo -e "\n{NC}"

log_info "Unmounting '$BLOCK_DEVICE'..."

if mountpoint -q "BLOCK_DEVICE" /proc/mounts; then

umount "BLOCK_DEVICE"

log_success "Successfully unmounted '$BLOCK_DEVICE'."

else

log_info "'$BLOCK_DEVICE' is already unmounted."

fi

log_warn "formatting '$BLOCK_DEVICE' to Ext4 in 5 seconds. Press Ctrl+C to abort now!"

sleep 5

log_info "Formatting '$BLOCK_DEVICE' with mkfs.ext4..."

mkfs.ext4 "$BLOCK_DEVICE"

log_success "Partition formatted to Ext4 successfully."

# ------------------------------------------------------------------------------

# 5. Step 3: Get New UUID & Guide fstab Updates

# ------------------------------------------------------------------------------

echo -e "\n{NC}"

NEW_UUID=BLOCK_DEVICE")

log_info "New partition UUID: $NEW_UUID"

FSTAB_LINE="UUID=$NEW_UUID $SOURCE_MOUNT ext4 defaults,noatime,x-systemd.mount-timeout=10s 0 2"

echo -e "\n{NC}"

echo -e "Replace the old Btrfs entry for '$SOURCE_MOUNT' with the following line:\n"

echo -e "FSTAB_LINE${NC}\n"

echo "Options used:"

echo " - defaults: Standard mounting options."

echo " - noatime: Disables writing access times to increase speed and decrease disk wear."

echo " - x-systemd.mount-timeout=10s: Safe systemd timeout to avoid boot hang in case of failure."

echo " - 0: Disables dump backup."

echo " - 2: Performs fsck check on boot after root."

echo ""

read -rp "Press [Enter] after you have updated and saved /etc/fstab (you can do this in another terminal tab)." DUMMY

# ------------------------------------------------------------------------------

# 6. Step 4: Verification and Mount Test

# ------------------------------------------------------------------------------

echo -e "\n{NC}"

log_info "Checking /etc/fstab structure using findmnt..."

if! findmnt --verify; then

log_error "/etc/fstab verification failed! Please fix your fstab before continuing."

exit 1

fi

log_success "fstab syntax and structure verified successfully."

log_info "Testing mount of configured paths..."

# Unmount if target path is active to ensure we test mount-a cleanly

if mountpoint -q "$SOURCE_MOUNT"; then

umount "$SOURCE_MOUNT"

fi

log_info "Running 'mount -a -v' to test the new configuration..."

mount -a -v

# Verify active mount point

if findmnt "$SOURCE_MOUNT" > /dev/null; then

log_success "The partition successfully mounted to '$SOURCE_MOUNT' using the new /etc/fstab configuration."

df -h "$SOURCE_MOUNT"

else

log_error "Failed to mount the partition to '$SOURCE_MOUNT'. Please check fstab."

exit 1

fi

# ------------------------------------------------------------------------------

# 7. Step 5: Restore Phase

# ------------------------------------------------------------------------------

echo -e "\n{NC}"

log_info "Restoring files from backup location (RSYNC_SOURCE)..."

rsync -aHAXv --numeric-ids --progress "RSYNC_SOURCE"

log_success "Data restore complete!"

echo -e "\n{NC}"

echo -e " Migration of '$BLOCK_DEVICE' from Btrfs to Ext4 is fully complete!"

echo -e " Your partition is mounted at '$SOURCE_MOUNT' and your files are restored."

echo -e "======================================================================${NC}"


Gemini

Data Loss Hazard

This script formats a storage drive (mkfs.ext4). If you enter the wrong block device name during the interactive prompts, you will permanently erase data. Ensure you have an external backup before proceeding.

To run this script on a Linux system, save the code to a file, make it executable, and run it with sudo privileges.

1

Save the script to a file

Terminal command

Open a terminal and save the content into a script file named btrfs_to_ext4.sh using your preferred text editor (e.g., nano):

nano btrfs_to_ext4.sh

Paste the script into the file, save, and exit (Ctrl+O, Enter, then Ctrl+X in nano).

2

Make the script executable

Permissions setup

Grant execution permissions to the script file:

chmod +x btrfs_to_ext4.sh

3

Identify your paths and drives

Prerequisite data collection

Before executing, run lsblk and df -h in your terminal to note down:

  • Current Btrfs mount path (e.g., /mnt/btrfs-source)
  • Backup destination path (must be on a different drive/partition with enough free space to hold all your data)
  • Target partition block device (e.g., /dev/sdb1)

4

Execute the script with root privileges

Requires sudo

Run the script using sudo:

sudo ./btrfs_to_ext4.sh

5

Follow the interactive prompts

During execution

The script will prompt you for inputs sequentially:

  1. Enter the current mount path.
  2. Enter the backup location path.
  3. Enter the block device (e.g., /dev/sdXN).
  4. Type YES in all caps to confirm formatting.
  5. When prompted in Step 3, open a separate terminal window to update /etc/fstab with the generated line before pressing [Enter] to finish.

You

Can you guide me step-by-step on how to edit /etc/fstab safely?


Gemini

Editing /etc/fstab requires root privileges. Because syntax errors or incorrect UUIDs can prevent your Linux system from booting, always create a backup copy before making changes and verify your changes before rebooting.

System Boot Hazard

An invalid line in /etc/fstab can cause systemd to fail to mount root or local drives during startup, dropping you into an emergency recovery shell. Always run verification commands before rebooting.

1

Create a backup of /etc/fstab

Safety prerequisite

Open your terminal and copy the current working configuration file to a safe backup location:

sudo cp /etc/fstab /etc/fstab.bak

2

Open the file in a text editor

Terminal command

Use a simple text editor like nano with root privileges:

sudo nano /etc/fstab

3

Navigate using your keyboard's arrow keys.

  • To replace an existing line: Locate the old Btrfs entry for your mount point, use Ctrl+K to delete the line, and type (or paste) your new Ext4 entry.
  • To add a new line: Scroll to the bottom of the file and add your line on a new row.

Ensure fields are separated by single spaces or tabs: UUID=<your-uuid> <mount-point> ext4 defaults,noatime,x-systemd.mount-timeout=10s 0 2

4

Save and exit nano

Nano shortcuts

  1. Press Ctrl + O and press Enter to write the file.
  2. Press Ctrl + X to exit the editor.

5

Verify the configuration

Critical step before rebooting

Verify the file syntax and test mounting without rebooting:

sudo findmnt --verify

If findmnt returns errors, re-open /etc/fstab and fix the syntax immediately. If it passes, test mounting all filesystems defined in fstab:

sudo mount -a -v

If mount -a completes without throwing errors, your /etc/fstab configuration is safe and working.

What to do if something goes wrong

If findmnt fails or mount -a throws an error, you can immediately restore your working backup with:

sudo cp /etc/fstab.bak /etc/fstab

Where would you like to go next?