A bash-based backup utility for Android devices using ADB. In essence, it copies and zips (optionally with a password) specified folders, along with an option to export files to Google Drive.
# Install ADB via Homebrew
brew install android-platform-tools# Install zip (usually pre-installed on macOS)
brew install zip# Optional: Install gws (Google Workspace CLI) for Google Drive export
brew install googleworkspace-cli- Enable USB debugging on your Android device (Settings > Developer Options > USB Debugging)
- Connect your device via USB
- Authorize the connection when prompted on your device
git clone https://github.com/your-username/android-backup.git
cd android-backup
chmod +x android-backup.sh./android-backup.sh devicesExample output:
Connected devices:
- 1A2B3C4D5E6F (device)
- 192.168.1.100:5555 (device)
./android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --dry-runExample output:
=== DRY RUN MODE ===
Output would be: ./backup_2026-02-18_130044
Files to backup:
Folder: /sdcard/DCIM
============================================================
File Size Modified
------------------------------------------------------------
Camera/ <DIR> 2026-02-15 10:30
IMG_20260215_103045.jpg 3.5 MB 2026-02-15 10:30
IMG_20260216_142233.jpg 4.2 MB 2026-02-16 14:22
------------------------------------------------------------
Summary: 2 files, 7.70 MB
=== END DRY RUN ===
./android-backup.sh backup --folders "/sdcard/DCIM,/sdcard/Download" --output ./backupExample output:
Starting backup to: ./backup_2026-02-18_130044
[1/2] Copying /sdcard/DCIM...
/sdcard/DCIM/: 15 files pulled, 0 skipped.
[2/2] Copying /sdcard/Download...
/sdcard/Download/: 8 files pulled, 0 skipped.
Backup completed: ./backup_2026-02-18_130044
./android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --archiveExample output:
Starting backup to: ./backup_2026-02-18_130044
[1/1] Copying /sdcard/DCIM...
/sdcard/DCIM/: 15 files pulled, 0 skipped.
Backup completed: ./backup_2026-02-18_130044
Creating archive: ./backup_2026-02-18_130044.zip...
Archive created successfully.
Uncompressed backup folder removed.
./android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --archive --password "mypassword"Example output:
Starting backup to: ./backup_2026-02-18_130044
[1/1] Copying /sdcard/DCIM...
/sdcard/DCIM/: 15 files pulled, 0 skipped.
Backup completed: ./backup_2026-02-18_130044
Creating archive: ./backup_2026-02-18_130044.zip...
Using password protection for archive.
Archive created successfully.
Uncompressed backup folder removed.
Use the export-gdrive.sh script to upload a backup archive to Google Drive. This script requires gws (Google Workspace CLI) to be installed and authenticated.
1. Install gws:
brew install googleworkspace-cli
# or: npm install -g @googleworkspace/cli2. Authenticate:
gws auth setup # one-time setup
gws auth login # log in to Google3. Upload:
./export-gdrive.sh ./backup_2026-02-18_130044.zip "YOUR_FOLDER_ID"Note: The second argument must be a Google Drive folder ID, not a folder name. To find it, open the folder in Google Drive web UI and copy the ID from the URL (
https://drive.google.com/drive/folders/FOLDER_ID).
Example output:
Uploading ./backup_2026-02-18_130044.zip to Google Drive folder ID: 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms...
Upload completed successfully.
You can chain android-backup.sh and export-gdrive.sh into a single command to back up, archive, and upload in one go.
Using --quiet flag:
The --quiet flag suppresses progress messages and prints only the final archive or directory path to stdout, making it safe to pipe directly into export-gdrive.sh.
./android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --archive --quiet | \
./export-gdrive.sh - "YOUR_FOLDER_ID"With password protection:
./android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --archive --password --quiet | \
./export-gdrive.sh - "YOUR_FOLDER_ID"Note:
--quietcannot be used with--dry-run.
./android-backup.sh --helpExample output:
Usage: android-backup.sh COMMAND [OPTIONS]
Commands:
devices List connected Android devices
backup [OPTIONS] Backup folders from the connected device
Backup Options:
--folders <paths> Comma-separated list of folders to backup (required)
--output <path> Output folder for backup (required)
--dry-run Show what would be backed up without copying
--archive Create a zip archive of the backup
--password <pass> Set password for the archive
--quiet Suppress progress output; print only the final path
Global Options:
--help, -h Display this help message
Examples:
android-backup.sh devices
android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --dry-run
android-backup.sh backup --folders "/sdcard/DCIM,/sdcard/Download" --output ./backup --archive
android-backup.sh backup --folders "/sdcard/DCIM" --output ./backup --archive --quiet
Contributions are more than welcome! Please follow the guidelines in CONTRIBUTING.md
Every script declares a finish function paired with a trap:
finish() {
local result=${?}# Cleanup code goes here (e.g. rm -f "${tmpfile}")exit${result}
}
trap finish EXIT ERRThis pattern ensures that:
- Cleanup runs on any exit path — whether the script succeeds, fails, or is interrupted.
- The original exit code is preserved —
local result=${?}captures the exit status before any cleanup commands execute, so the script returns the same code it would have returned without the trap.
Currently, the finish function is a no-op placeholder; it exists so that future cleanup (temporary files,
unmounting a drive, kill a backgroud process, restore terminal settings, etc.) can be added in one central location
without risk of leaking resources or masking failure codes.