generated from nhcarrigan/template
feat: add adb scripts
This commit is contained in:
@@ -17,6 +17,7 @@ help:
|
||||
@echo ""
|
||||
@echo "Running scripts:"
|
||||
@echo " make run - Interactive script runner (select language, category, script)"
|
||||
@echo " make run-bash - Run a bash script (e.g., make run-bash SCRIPT=bash/adb/push.sh)"
|
||||
|
||||
# Install all dependencies
|
||||
install: install-ts install-py
|
||||
@@ -76,3 +77,16 @@ clean:
|
||||
# Interactive script runner
|
||||
run:
|
||||
@./run.sh
|
||||
|
||||
# Run a specific bash script
|
||||
run-bash:
|
||||
@if [ -z "$(SCRIPT)" ]; then \
|
||||
echo "Please specify a script: make run-bash SCRIPT=bash/adb/push.sh"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@if [ ! -f "$(SCRIPT)" ]; then \
|
||||
echo "Script not found: $(SCRIPT)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "Running bash script: $(SCRIPT)"
|
||||
@op run --env-file=prod.env --no-masking -- bash "$(SCRIPT)"
|
||||
@@ -0,0 +1,150 @@
|
||||
# ADB File Transfer Scripts
|
||||
|
||||
Easy-to-use bash scripts for transferring files between your computer and Android device using ADB.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Android Debug Bridge (ADB) installed and in your PATH
|
||||
- USB debugging enabled on your Android device
|
||||
- Device connected via USB cable
|
||||
|
||||
### Installing ADB
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install android-tools-adb
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
```bash
|
||||
brew install android-platform-tools
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
Download from [Android Developer website](https://developer.android.com/studio/releases/platform-tools)
|
||||
|
||||
## Scripts Overview
|
||||
|
||||
### 🚀 push.sh - Push files to Android
|
||||
Transfer files from your computer to your Android device.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Interactive mode (recommended)
|
||||
./push.sh
|
||||
|
||||
# Direct mode
|
||||
./push.sh ~/Documents/file.pdf /sdcard/Download/
|
||||
./push.sh ~/Pictures/vacation/ /sdcard/Pictures/
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Interactive mode with common destination suggestions
|
||||
- Automatic path validation
|
||||
- Directory creation if needed
|
||||
- Progress feedback
|
||||
- Support for both files and directories
|
||||
|
||||
### 📥 pull.sh - Pull files from Android
|
||||
Transfer files from your Android device to your computer.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Interactive mode (recommended)
|
||||
./pull.sh
|
||||
|
||||
# Direct mode
|
||||
./pull.sh /sdcard/DCIM/Camera/ ~/Pictures/phone-backup/
|
||||
./pull.sh /sdcard/Download/document.pdf ~/Downloads/
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Browse Android filesystem interactively
|
||||
- Quick access to common folders
|
||||
- File count and size summary
|
||||
- Creates destination directories automatically
|
||||
- Support for both files and directories
|
||||
|
||||
### 📱 adb-transfer.sh - All-in-One Menu
|
||||
Interactive menu system for all file transfer operations.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
./adb-transfer.sh
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Device status and information display
|
||||
- Quick actions (backup photos, screenshots, WhatsApp media)
|
||||
- Access to push/pull scripts
|
||||
- Device information viewer
|
||||
- Beautiful CLI interface
|
||||
|
||||
## Common Android Paths
|
||||
|
||||
- `/sdcard/Download/` - Downloads folder
|
||||
- `/sdcard/DCIM/Camera/` - Camera photos and videos
|
||||
- `/sdcard/Pictures/` - General pictures folder
|
||||
- `/sdcard/Screenshots/` - Screenshots (varies by device)
|
||||
- `/sdcard/WhatsApp/Media/` - WhatsApp media files
|
||||
- `/sdcard/Documents/` - Documents folder
|
||||
- `/sdcard/Music/` - Music files
|
||||
- `/sdcard/Movies/` - Video files
|
||||
|
||||
## Making Scripts Executable
|
||||
|
||||
First time setup:
|
||||
```bash
|
||||
chmod +x push.sh pull.sh adb-transfer.sh
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Backup all camera photos
|
||||
```bash
|
||||
./pull.sh /sdcard/DCIM/Camera/ ~/Pictures/android-backup/
|
||||
```
|
||||
|
||||
### Push multiple PDFs to Downloads
|
||||
```bash
|
||||
./push.sh ~/Documents/*.pdf /sdcard/Download/
|
||||
```
|
||||
|
||||
### Interactive file browser
|
||||
```bash
|
||||
./pull.sh
|
||||
# Then select option 1 to browse filesystem
|
||||
```
|
||||
|
||||
### Quick backup using menu
|
||||
```bash
|
||||
./adb-transfer.sh
|
||||
# Select option 3 for quick actions
|
||||
# Select option 1 to backup all camera photos
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "No device connected" error
|
||||
1. Check USB cable connection
|
||||
2. Enable USB debugging: Settings → Developer options → USB debugging
|
||||
3. Accept the authorization prompt on your phone
|
||||
4. Try `adb devices` to verify connection
|
||||
|
||||
### "Permission denied" errors
|
||||
- Some system directories require root access
|
||||
- Stick to `/sdcard/` paths for normal usage
|
||||
|
||||
### Slow transfer speeds
|
||||
- Use USB 3.0 ports and cables when possible
|
||||
- Large files/directories take time - the scripts show progress
|
||||
|
||||
## Tips
|
||||
|
||||
1. **Use interactive mode** - It's easier and prevents typos
|
||||
2. **Backup regularly** - Use the quick actions menu for easy backups
|
||||
3. **Check free space** - Use device info option to see available storage
|
||||
4. **Organize transfers** - The scripts create timestamped folders for backups
|
||||
|
||||
## Created with 💕 by Naomi & Hikari
|
||||
Executable
+225
@@ -0,0 +1,225 @@
|
||||
#!/bin/bash
|
||||
# Interactive ADB file transfer menu
|
||||
# Author: Naomi Carrigan & Hikari 💕
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color codes for pretty output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
MAGENTA='\033[0;35m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ASCII art banner
|
||||
banner() {
|
||||
echo -e "${CYAN}"
|
||||
echo "╔═══════════════════════════════════╗"
|
||||
echo "║ 📱 ADB File Transfer 📱 ║"
|
||||
echo "║ Made with 💕 by Hikari ║"
|
||||
echo "╚═══════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# Check if ADB is available and device connected
|
||||
check_adb_status() {
|
||||
if ! command -v adb &> /dev/null; then
|
||||
echo -e "${RED}❌ ADB not found${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if adb devices | grep -q "device$"; then
|
||||
local device=$(adb devices | grep "device$" | awk '{print $1}')
|
||||
local model=$(adb shell getprop ro.product.model 2>/dev/null | tr -d '\r\n')
|
||||
local android_version=$(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r\n')
|
||||
|
||||
echo -e "${GREEN}✅ Device connected${NC}"
|
||||
echo -e "${YELLOW}📱 Model: ${model:-Unknown}${NC}"
|
||||
echo -e "${YELLOW}🤖 Android: ${android_version:-Unknown}${NC}"
|
||||
echo -e "${YELLOW}🔌 ID: ${device}${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}❌ No device connected${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Quick actions menu
|
||||
quick_actions() {
|
||||
echo -e "\n${BLUE}⚡ Quick Actions${NC}"
|
||||
echo "1) Pull all photos from camera"
|
||||
echo "2) Pull all screenshots"
|
||||
echo "3) Pull WhatsApp media"
|
||||
echo "4) Push files to Downloads"
|
||||
echo "5) Back to main menu"
|
||||
echo ""
|
||||
|
||||
read -p "Select action (1-5): " action
|
||||
|
||||
case $action in
|
||||
1)
|
||||
# Pull camera photos
|
||||
echo -e "${CYAN}📸 Pulling camera photos...${NC}"
|
||||
local backup_dir="$HOME/Pictures/android-camera-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$backup_dir"
|
||||
|
||||
if adb pull /sdcard/DCIM/Camera/ "$backup_dir/"; then
|
||||
echo -e "${GREEN}✅ Photos backed up to: $backup_dir${NC}"
|
||||
echo "Files: $(find "$backup_dir" -type f | wc -l)"
|
||||
echo "Size: $(du -sh "$backup_dir" | cut -f1)"
|
||||
else
|
||||
echo -e "${RED}❌ Failed to pull photos${NC}"
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
# Pull screenshots
|
||||
echo -e "${CYAN}📸 Pulling screenshots...${NC}"
|
||||
local screenshot_dir="$HOME/Pictures/android-screenshots-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$screenshot_dir"
|
||||
|
||||
# Try multiple possible screenshot locations
|
||||
local found=false
|
||||
for path in "/sdcard/Pictures/Screenshots" "/sdcard/Screenshots" "/sdcard/DCIM/Screenshots"; do
|
||||
if adb shell "test -d '$path' && echo 'exists'" 2>/dev/null | grep -q "exists"; then
|
||||
if adb pull "$path" "$screenshot_dir/"; then
|
||||
found=true
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$found" == true ]]; then
|
||||
echo -e "${GREEN}✅ Screenshots backed up to: $screenshot_dir${NC}"
|
||||
echo "Files: $(find "$screenshot_dir" -type f | wc -l)"
|
||||
else
|
||||
echo -e "${RED}❌ No screenshots found or failed to pull${NC}"
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
# Pull WhatsApp media
|
||||
echo -e "${CYAN}💬 Pulling WhatsApp media...${NC}"
|
||||
local whatsapp_dir="$HOME/Pictures/whatsapp-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$whatsapp_dir"
|
||||
|
||||
if adb shell "test -d '/sdcard/WhatsApp/Media' && echo 'exists'" 2>/dev/null | grep -q "exists"; then
|
||||
if adb pull /sdcard/WhatsApp/Media/ "$whatsapp_dir/"; then
|
||||
echo -e "${GREEN}✅ WhatsApp media backed up to: $whatsapp_dir${NC}"
|
||||
echo "Files: $(find "$whatsapp_dir" -type f | wc -l)"
|
||||
echo "Size: $(du -sh "$whatsapp_dir" | cut -f1)"
|
||||
else
|
||||
echo -e "${RED}❌ Failed to pull WhatsApp media${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}❌ WhatsApp media folder not found${NC}"
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
# Push to Downloads
|
||||
echo -e "${CYAN}📤 Push files to Downloads folder${NC}"
|
||||
read -p "Enter file/folder path to push: " -e local_path
|
||||
local_path="${local_path/#\~/$HOME}"
|
||||
|
||||
if [[ -e "$local_path" ]]; then
|
||||
if adb push "$local_path" /sdcard/Download/; then
|
||||
echo -e "${GREEN}✅ Files pushed to Downloads folder${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Failed to push files${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}❌ Path not found: $local_path${NC}"
|
||||
fi
|
||||
;;
|
||||
5)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Invalid choice${NC}"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
read -p "Press Enter to continue..."
|
||||
}
|
||||
|
||||
# Device info
|
||||
device_info() {
|
||||
echo -e "\n${BLUE}📱 Device Information${NC}"
|
||||
echo "================================"
|
||||
|
||||
# Basic info
|
||||
echo -e "${YELLOW}Model:${NC} $(adb shell getprop ro.product.model 2>/dev/null | tr -d '\r\n')"
|
||||
echo -e "${YELLOW}Manufacturer:${NC} $(adb shell getprop ro.product.manufacturer 2>/dev/null | tr -d '\r\n')"
|
||||
echo -e "${YELLOW}Android Version:${NC} $(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r\n')"
|
||||
echo -e "${YELLOW}SDK Version:${NC} $(adb shell getprop ro.build.version.sdk 2>/dev/null | tr -d '\r\n')"
|
||||
|
||||
# Storage info
|
||||
echo -e "\n${CYAN}Storage:${NC}"
|
||||
adb shell df -h /sdcard | tail -n 1 | awk '{print " Used: " $3 " / " $2 " (" $5 ")"}'
|
||||
|
||||
# Battery info
|
||||
echo -e "\n${CYAN}Battery:${NC}"
|
||||
local battery_level=$(adb shell dumpsys battery | grep "level:" | awk '{print $2}')
|
||||
local battery_status=$(adb shell dumpsys battery | grep "status:" | awk '{print $2}')
|
||||
echo " Level: ${battery_level}%"
|
||||
echo " Status: ${battery_status}"
|
||||
|
||||
echo ""
|
||||
read -p "Press Enter to continue..."
|
||||
}
|
||||
|
||||
# Main menu
|
||||
main_menu() {
|
||||
while true; do
|
||||
clear
|
||||
banner
|
||||
|
||||
# Check device status
|
||||
echo -e "${MAGENTA}Device Status:${NC}"
|
||||
if ! check_adb_status; then
|
||||
echo -e "\n${YELLOW}Please connect your Android device and enable USB debugging${NC}"
|
||||
echo ""
|
||||
read -p "Press Enter to retry or Ctrl+C to exit..."
|
||||
continue
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}Main Menu:${NC}"
|
||||
echo "1) Push files to Android"
|
||||
echo "2) Pull files from Android"
|
||||
echo "3) Quick actions"
|
||||
echo "4) Device information"
|
||||
echo "5) Exit"
|
||||
echo ""
|
||||
|
||||
read -p "Select option (1-5): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
echo -e "\n${CYAN}Starting push mode...${NC}\n"
|
||||
bash "$(dirname "$0")/push.sh"
|
||||
;;
|
||||
2)
|
||||
echo -e "\n${CYAN}Starting pull mode...${NC}\n"
|
||||
bash "$(dirname "$0")/pull.sh"
|
||||
;;
|
||||
3)
|
||||
quick_actions
|
||||
;;
|
||||
4)
|
||||
device_info
|
||||
;;
|
||||
5)
|
||||
echo -e "${GREEN}👋 Goodbye!${NC}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Invalid choice${NC}"
|
||||
sleep 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Run main menu
|
||||
main_menu
|
||||
Executable
+298
@@ -0,0 +1,298 @@
|
||||
#!/bin/bash
|
||||
# Pull files from Android device via ADB
|
||||
# Author: Naomi Carrigan & Hikari 💕
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color codes for pretty output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to display usage
|
||||
usage() {
|
||||
echo -e "${BLUE}Usage: $0 [android_source] [local_destination]${NC}"
|
||||
echo -e "${YELLOW}If no arguments provided, interactive mode will start${NC}"
|
||||
echo ""
|
||||
echo "Common Android paths:"
|
||||
echo " /sdcard/Download/ - Downloads folder"
|
||||
echo " /sdcard/DCIM/ - Camera folder"
|
||||
echo " /sdcard/Pictures/ - Pictures folder"
|
||||
echo " /sdcard/WhatsApp/ - WhatsApp media"
|
||||
echo " /sdcard/Screenshots/ - Screenshots"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 /sdcard/DCIM/Camera/ ~/Pictures/phone-backup/"
|
||||
echo " $0 /sdcard/Download/document.pdf ~/Downloads/"
|
||||
echo " $0"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to check if ADB is installed and device is connected
|
||||
check_adb() {
|
||||
if ! command -v adb &> /dev/null; then
|
||||
echo -e "${RED}❌ Error: ADB is not installed or not in PATH${NC}"
|
||||
echo "Please install Android Debug Bridge (ADB) first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if device is connected
|
||||
if ! adb devices | grep -q "device$"; then
|
||||
echo -e "${RED}❌ Error: No Android device connected${NC}"
|
||||
echo "Please connect your device and enable USB debugging"
|
||||
echo ""
|
||||
echo "Current devices:"
|
||||
adb devices
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to browse Android filesystem
|
||||
browse_android_fs() {
|
||||
local current_path="${1:-/sdcard/}"
|
||||
|
||||
while true; do
|
||||
echo -e "${CYAN}📱 Current path: $current_path${NC}"
|
||||
echo ""
|
||||
|
||||
# List contents
|
||||
echo -e "${YELLOW}Contents:${NC}"
|
||||
local items=$(adb shell "ls -la '$current_path' 2>/dev/null" | tail -n +2 | awk '{print $NF}' | grep -v "^\.$" | grep -v "^\.\.$")
|
||||
|
||||
local i=1
|
||||
local -a entries=()
|
||||
|
||||
# Add parent directory option if not at root
|
||||
if [[ "$current_path" != "/" ]]; then
|
||||
echo "0) .. (Go up)"
|
||||
entries[0]=".."
|
||||
fi
|
||||
|
||||
# List items
|
||||
while IFS= read -r item; do
|
||||
if [[ -n "$item" ]]; then
|
||||
# Check if directory
|
||||
if adb shell "test -d '$current_path/$item' 2>/dev/null && echo 'dir'" | grep -q "dir"; then
|
||||
echo "$i) $item/"
|
||||
else
|
||||
echo "$i) $item"
|
||||
fi
|
||||
entries[$i]="$item"
|
||||
((i++))
|
||||
fi
|
||||
done <<< "$items"
|
||||
|
||||
echo ""
|
||||
echo "s) Select this path"
|
||||
echo "q) Quit"
|
||||
echo ""
|
||||
|
||||
read -p "Enter choice: " choice
|
||||
|
||||
case $choice in
|
||||
s|S)
|
||||
echo "$current_path"
|
||||
return 0
|
||||
;;
|
||||
q|Q)
|
||||
return 1
|
||||
;;
|
||||
0)
|
||||
if [[ "$current_path" != "/" ]]; then
|
||||
current_path=$(dirname "$current_path")
|
||||
fi
|
||||
;;
|
||||
[0-9]*)
|
||||
if [[ -n "${entries[$choice]:-}" ]]; then
|
||||
local selected="${entries[$choice]}"
|
||||
local new_path="$current_path/$selected"
|
||||
# Clean up path
|
||||
new_path=$(echo "$new_path" | sed 's|//|/|g')
|
||||
|
||||
# Check if it's a directory
|
||||
if adb shell "test -d '$new_path' 2>/dev/null && echo 'dir'" | grep -q "dir"; then
|
||||
current_path="$new_path"
|
||||
else
|
||||
# It's a file, return it
|
||||
echo "$new_path"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}Invalid choice${NC}"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Invalid choice${NC}"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
done
|
||||
}
|
||||
|
||||
# Interactive mode
|
||||
interactive_mode() {
|
||||
echo -e "${BLUE}📲 ADB Pull - Interactive Mode${NC}"
|
||||
echo ""
|
||||
|
||||
# Choose method
|
||||
echo -e "${YELLOW}How would you like to select the source?${NC}"
|
||||
echo "1) Browse Android filesystem"
|
||||
echo "2) Enter path directly"
|
||||
echo "3) Quick access to common folders"
|
||||
echo ""
|
||||
|
||||
read -p "Select method (1-3): " method
|
||||
|
||||
case $method in
|
||||
1)
|
||||
# Browse mode
|
||||
if source_path=$(browse_android_fs); then
|
||||
echo -e "${GREEN}Selected: $source_path${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Cancelled${NC}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
# Direct path entry
|
||||
read -p "Enter Android source path: " -e source_path
|
||||
;;
|
||||
3)
|
||||
# Quick access
|
||||
echo ""
|
||||
echo -e "${YELLOW}Common locations:${NC}"
|
||||
echo "1) /sdcard/DCIM/Camera/"
|
||||
echo "2) /sdcard/Pictures/"
|
||||
echo "3) /sdcard/Download/"
|
||||
echo "4) /sdcard/WhatsApp/Media/"
|
||||
echo "5) /sdcard/Screenshots/"
|
||||
echo "6) /sdcard/Documents/"
|
||||
echo "7) /sdcard/Music/"
|
||||
echo ""
|
||||
|
||||
read -p "Select location (1-7): " quick_choice
|
||||
|
||||
case $quick_choice in
|
||||
1) source_path="/sdcard/DCIM/Camera/" ;;
|
||||
2) source_path="/sdcard/Pictures/" ;;
|
||||
3) source_path="/sdcard/Download/" ;;
|
||||
4) source_path="/sdcard/WhatsApp/Media/" ;;
|
||||
5) source_path="/sdcard/Screenshots/" ;;
|
||||
6) source_path="/sdcard/Documents/" ;;
|
||||
7) source_path="/sdcard/Music/" ;;
|
||||
*)
|
||||
echo -e "${RED}❌ Invalid choice${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ Invalid choice${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get destination
|
||||
echo ""
|
||||
read -p "Enter local destination path (default: current directory): " -e dest_path
|
||||
dest_path="${dest_path:-.}"
|
||||
dest_path="${dest_path/#\~/$HOME}"
|
||||
|
||||
# Pull the file/directory
|
||||
pull_from_android "$source_path" "$dest_path"
|
||||
}
|
||||
|
||||
# Function to pull files from Android
|
||||
pull_from_android() {
|
||||
local source="$1"
|
||||
local dest="$2"
|
||||
|
||||
# Validate source exists
|
||||
if ! adb shell "test -e '$source' 2>/dev/null && echo 'exists'" | grep -q "exists"; then
|
||||
echo -e "${RED}❌ Error: Source '$source' does not exist on device${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create destination directory if needed
|
||||
if [[ ! -d "$dest" ]]; then
|
||||
mkdir -p "$dest"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}📥 Pulling from Android device...${NC}"
|
||||
echo "Source: $source"
|
||||
echo "Destination: $dest"
|
||||
echo ""
|
||||
|
||||
# Check if source is directory
|
||||
if adb shell "test -d '$source' 2>/dev/null && echo 'dir'" | grep -q "dir"; then
|
||||
echo -e "${YELLOW}Pulling directory...${NC}"
|
||||
|
||||
# Count files for progress
|
||||
local file_count=$(adb shell "find '$source' -type f 2>/dev/null | wc -l" | tr -d '\r\n')
|
||||
echo "Found $file_count files to pull"
|
||||
echo ""
|
||||
|
||||
if adb pull "$source" "$dest"; then
|
||||
echo -e "${GREEN}✅ Directory pulled successfully!${NC}"
|
||||
|
||||
# Show summary
|
||||
local pulled_dir="$dest/$(basename "$source")"
|
||||
if [[ -d "$pulled_dir" ]]; then
|
||||
echo ""
|
||||
echo -e "${BLUE}📊 Summary:${NC}"
|
||||
echo "Location: $pulled_dir"
|
||||
echo "Files: $(find "$pulled_dir" -type f | wc -l)"
|
||||
echo "Total size: $(du -sh "$pulled_dir" | cut -f1)"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}❌ Failed to pull directory${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Single file
|
||||
if adb pull "$source" "$dest"; then
|
||||
echo -e "${GREEN}✅ File pulled successfully!${NC}"
|
||||
|
||||
# Show file info
|
||||
local filename=$(basename "$source")
|
||||
local full_path="$dest/$filename"
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}📄 File info:${NC}"
|
||||
ls -lh "$full_path"
|
||||
else
|
||||
echo -e "${RED}❌ Failed to pull file${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main script
|
||||
main() {
|
||||
check_adb
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
# No arguments, run interactive mode
|
||||
interactive_mode
|
||||
elif [[ $# -eq 1 ]]; then
|
||||
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
|
||||
usage
|
||||
else
|
||||
echo -e "${RED}❌ Error: Missing destination path${NC}"
|
||||
usage
|
||||
fi
|
||||
elif [[ $# -eq 2 ]]; then
|
||||
# Arguments provided
|
||||
dest_path="${2/#\~/$HOME}"
|
||||
pull_from_android "$1" "$dest_path"
|
||||
else
|
||||
echo -e "${RED}❌ Error: Too many arguments${NC}"
|
||||
usage
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+202
@@ -0,0 +1,202 @@
|
||||
#!/bin/bash
|
||||
# Push files to Android device via ADB
|
||||
# Author: Naomi Carrigan & Hikari 💕
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color codes for pretty output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to display usage
|
||||
usage() {
|
||||
echo -e "${BLUE}Usage: $0 [source_file/directory] [android_destination]${NC}"
|
||||
echo -e "${YELLOW}If no arguments provided, interactive mode will start${NC}"
|
||||
echo ""
|
||||
echo "Common Android paths:"
|
||||
echo " /sdcard/Download/ - Downloads folder"
|
||||
echo " /sdcard/DCIM/ - Camera folder"
|
||||
echo " /sdcard/Pictures/ - Pictures folder"
|
||||
echo " /sdcard/Documents/ - Documents folder"
|
||||
echo " /sdcard/Music/ - Music folder"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 photo.jpg /sdcard/Pictures/"
|
||||
echo " $0 ~/Documents/file.pdf /sdcard/Download/"
|
||||
echo " $0"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to check if ADB is installed and device is connected
|
||||
check_adb() {
|
||||
if ! command -v adb &> /dev/null; then
|
||||
echo -e "${RED}❌ Error: ADB is not installed or not in PATH${NC}"
|
||||
echo "Please install Android Debug Bridge (ADB) first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if device is connected
|
||||
if ! adb devices | grep -q "device$"; then
|
||||
echo -e "${RED}❌ Error: No Android device connected${NC}"
|
||||
echo "Please connect your device and enable USB debugging"
|
||||
echo ""
|
||||
echo "Current devices:"
|
||||
adb devices
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to validate Android path
|
||||
validate_android_path() {
|
||||
local path="$1"
|
||||
|
||||
# Check if path starts with /
|
||||
if [[ ! "$path" =~ ^/ ]]; then
|
||||
echo -e "${YELLOW}⚠️ Warning: Path doesn't start with /, prepending /sdcard/${NC}"
|
||||
path="/sdcard/$path"
|
||||
fi
|
||||
|
||||
# Check if destination exists (create if it's a directory)
|
||||
if [[ "$path" =~ /$ ]]; then
|
||||
adb shell "mkdir -p '$path' 2>/dev/null || true"
|
||||
else
|
||||
# Check if parent directory exists
|
||||
local parent_dir=$(dirname "$path")
|
||||
adb shell "mkdir -p '$parent_dir' 2>/dev/null || true"
|
||||
fi
|
||||
|
||||
echo "$path"
|
||||
}
|
||||
|
||||
# Interactive mode
|
||||
interactive_mode() {
|
||||
echo -e "${BLUE}🚀 ADB Push - Interactive Mode${NC}"
|
||||
echo ""
|
||||
|
||||
# Get source file/directory
|
||||
read -p "Enter source file/directory path: " -e source_path
|
||||
|
||||
# Expand tilde and validate source
|
||||
source_path="${source_path/#\~/$HOME}"
|
||||
|
||||
if [[ ! -e "$source_path" ]]; then
|
||||
echo -e "${RED}❌ Error: Source '$source_path' does not exist${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Show common destinations
|
||||
echo ""
|
||||
echo -e "${YELLOW}Common Android destinations:${NC}"
|
||||
echo "1) /sdcard/Download/"
|
||||
echo "2) /sdcard/Pictures/"
|
||||
echo "3) /sdcard/DCIM/"
|
||||
echo "4) /sdcard/Documents/"
|
||||
echo "5) /sdcard/Music/"
|
||||
echo "6) /sdcard/Movies/"
|
||||
echo "7) Custom path"
|
||||
echo ""
|
||||
|
||||
read -p "Select destination (1-7): " choice
|
||||
|
||||
case $choice in
|
||||
1) dest_path="/sdcard/Download/" ;;
|
||||
2) dest_path="/sdcard/Pictures/" ;;
|
||||
3) dest_path="/sdcard/DCIM/" ;;
|
||||
4) dest_path="/sdcard/Documents/" ;;
|
||||
5) dest_path="/sdcard/Music/" ;;
|
||||
6) dest_path="/sdcard/Movies/" ;;
|
||||
7)
|
||||
read -p "Enter custom destination path: " -e dest_path
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ Invalid choice${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Push the file/directory
|
||||
push_to_android "$source_path" "$dest_path"
|
||||
}
|
||||
|
||||
# Function to push files to Android
|
||||
push_to_android() {
|
||||
local source="$1"
|
||||
local dest="$2"
|
||||
|
||||
# Validate destination path
|
||||
dest=$(validate_android_path "$dest")
|
||||
|
||||
echo -e "${BLUE}📦 Pushing to Android device...${NC}"
|
||||
echo "Source: $source"
|
||||
echo "Destination: $dest"
|
||||
echo ""
|
||||
|
||||
# Check if source is directory
|
||||
if [[ -d "$source" ]]; then
|
||||
echo -e "${YELLOW}Pushing directory...${NC}"
|
||||
# For directories, adb push handles recursion automatically
|
||||
if adb push "$source" "$dest"; then
|
||||
echo -e "${GREEN}✅ Directory pushed successfully!${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Failed to push directory${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Single file
|
||||
if adb push "$source" "$dest"; then
|
||||
echo -e "${GREEN}✅ File pushed successfully!${NC}"
|
||||
|
||||
# Show file info on device
|
||||
if [[ "$dest" =~ /$ ]]; then
|
||||
# Destination is a directory
|
||||
filename=$(basename "$source")
|
||||
full_path="${dest}${filename}"
|
||||
else
|
||||
# Destination is a file
|
||||
full_path="$dest"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}📱 File on device:${NC}"
|
||||
adb shell "ls -lh '$full_path'" 2>/dev/null || true
|
||||
else
|
||||
echo -e "${RED}❌ Failed to push file${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main script
|
||||
main() {
|
||||
check_adb
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
# No arguments, run interactive mode
|
||||
interactive_mode
|
||||
elif [[ $# -eq 1 ]]; then
|
||||
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
|
||||
usage
|
||||
else
|
||||
echo -e "${RED}❌ Error: Missing destination path${NC}"
|
||||
usage
|
||||
fi
|
||||
elif [[ $# -eq 2 ]]; then
|
||||
# Arguments provided
|
||||
source_path="${1/#\~/$HOME}"
|
||||
|
||||
if [[ ! -e "$source_path" ]]; then
|
||||
echo -e "${RED}❌ Error: Source '$source_path' does not exist${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
push_to_android "$source_path" "$2"
|
||||
else
|
||||
echo -e "${RED}❌ Error: Too many arguments${NC}"
|
||||
usage
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -13,9 +13,9 @@ DISCORD_CLIENT_SECRET="op://Private/Guild Counter/client secret"
|
||||
DISCORD_BOT_TOKEN="op://Environment Variables - Naomi/Amari/bot token"
|
||||
|
||||
# AWS
|
||||
AWS_ACCESS_KEY_ID="op://Private/Hetzner/S3 Access Key ID"
|
||||
AWS_SECRET_ACCESS_KEY="op://Private/Hetzner/S3 Secret Access Key"
|
||||
S3_ENDPOINT="op://Private/Hetzner/S3 Endpoint"
|
||||
AWS_ACCESS_KEY_ID="op://Private/S3/S3 Access Key ID"
|
||||
AWS_SECRET_ACCESS_KEY="op://Private/S3/S3 Secret Access Key"
|
||||
S3_ENDPOINT="op://Private/S3/S3 Endpoint"
|
||||
|
||||
# Gitea
|
||||
GITEA_TOKEN="op://Private/Gitea/token"
|
||||
|
||||
@@ -96,7 +96,7 @@ select_option() {
|
||||
|
||||
# Step 1: Select Language
|
||||
echo ""
|
||||
languages=("TypeScript" "Python")
|
||||
languages=("TypeScript" "Python" "Bash")
|
||||
select_option "Select a language:" "${languages[@]}"
|
||||
lang_index=$?
|
||||
language="${languages[$lang_index]}"
|
||||
@@ -109,7 +109,7 @@ if [ "$language" == "TypeScript" ]; then
|
||||
runner="pnpm tsx"
|
||||
# Get subdirectories as categories (excluding utils and interfaces)
|
||||
mapfile -t categories < <(find "$script_dir" -mindepth 1 -maxdepth 1 -type d ! -name 'utils' ! -name 'interfaces' -exec basename {} \; | sort)
|
||||
else
|
||||
elif [ "$language" == "Python" ]; then
|
||||
script_dir="python"
|
||||
runner="uv run python"
|
||||
# Get subdirectories as categories (excluding __pycache__ and .venv)
|
||||
@@ -118,6 +118,12 @@ else
|
||||
if ls "$script_dir"/*.py &>/dev/null 2>&1; then
|
||||
categories=("Root Scripts" "${categories[@]}")
|
||||
fi
|
||||
else # Bash
|
||||
script_dir="bash"
|
||||
runner="bash"
|
||||
# Get subdirectories as categories
|
||||
mapfile -t categories < <(find "$script_dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort)
|
||||
# Add "Root Scripts" option for bash files in root
|
||||
fi
|
||||
|
||||
if [ ${#categories[@]} -eq 0 ]; then
|
||||
@@ -134,13 +140,20 @@ echo -e "\n ${GREEN}$STAR Selected: ${WHITE}$category${RESET}\n"
|
||||
# Step 3: Get scripts in category
|
||||
if [ "$category" == "Root Scripts" ]; then
|
||||
search_dir="$script_dir"
|
||||
if [ "$language" == "Python" ]; then
|
||||
mapfile -t scripts < <(find "$search_dir" -maxdepth 1 -name "*.py" -exec basename {} \; | sort)
|
||||
elif [ "$language" == "Bash" ]; then
|
||||
mapfile -t scripts < <(find "$search_dir" -maxdepth 1 -name "*.sh" -exec basename {} \; | sort)
|
||||
fi
|
||||
elif [ "$language" == "TypeScript" ]; then
|
||||
search_dir="$script_dir/$category"
|
||||
mapfile -t scripts < <(find "$search_dir" -name "*.ts" -exec basename {} \; | sort)
|
||||
else
|
||||
elif [ "$language" == "Python" ]; then
|
||||
search_dir="$script_dir/$category"
|
||||
mapfile -t scripts < <(find "$search_dir" -name "*.py" ! -name "__init__.py" -exec basename {} \; | sort)
|
||||
else # Bash
|
||||
search_dir="$script_dir/$category"
|
||||
mapfile -t scripts < <(find "$search_dir" -name "*.sh" -exec basename {} \; | sort)
|
||||
fi
|
||||
|
||||
if [ ${#scripts[@]} -eq 0 ]; then
|
||||
@@ -159,8 +172,10 @@ if [ "$category" == "Root Scripts" ]; then
|
||||
script_path="$script"
|
||||
elif [ "$language" == "TypeScript" ]; then
|
||||
script_path="src/$category/$script"
|
||||
else
|
||||
elif [ "$language" == "Python" ]; then
|
||||
script_path="$category/$script"
|
||||
else # Bash
|
||||
script_path="bash/$category/$script"
|
||||
fi
|
||||
|
||||
# Show what we're about to run
|
||||
@@ -178,10 +193,13 @@ if [ "$language" == "TypeScript" ]; then
|
||||
cd typescript
|
||||
echo -e " ${DIM}$ op run --env-file=../prod.env -- $runner $script_path${RESET}\n"
|
||||
op run --env-file=../prod.env --no-masking -- $runner "$script_path"
|
||||
else
|
||||
elif [ "$language" == "Python" ]; then
|
||||
cd python
|
||||
echo -e " ${DIM}$ op run --env-file=../prod.env -- $runner $script_path${RESET}\n"
|
||||
op run --env-file=../prod.env --no-masking -- $runner "$script_path"
|
||||
else # Bash
|
||||
echo -e " ${DIM}$ op run --env-file=prod.env -- $runner $script_path${RESET}\n"
|
||||
op run --env-file=prod.env --no-masking -- $runner "$script_path"
|
||||
fi
|
||||
|
||||
exit_code=$?
|
||||
|
||||
Reference in New Issue
Block a user