Skip to content

Instantly share code, notes, and snippets.

@addohm
Last active May 23, 2026 13:21
Show Gist options
  • Select an option

  • Save addohm/1a630c181d1ceeb8a99bbf318864bbe0 to your computer and use it in GitHub Desktop.

Select an option

Save addohm/1a630c181d1ceeb8a99bbf318864bbe0 to your computer and use it in GitHub Desktop.
Download youtube content
#!/usr/bin/env bash
# ipad-util — manage files on an iOS app's Documents folder over USB.
# Works with any iOS app that opts into file sharing (UIFileSharingEnabled).
#
# Subcommands:
# put <path>... Transfer files/dirs into Documents (dirs walked manually).
# get <remote> [local] Pull a file/dir from device.
# ls [remote] List remote contents (default: Documents).
# rm [-f] <remote>... Delete files/dirs (prompts unless -f).
# mv <old> <new> Rename or move on device.
# mkdir <path> Create directory on device (recursive).
# sync <local-dir> Push only files not already present (name+size compare).
# info Device info: model, OS, name, free space, battery.
# space Free / total storage on device.
# battery Battery percentage and charging state.
# apps List user apps if ideviceinstaller is installed,
# otherwise print common bundle IDs and how to find more.
# screenshot [file.png] Capture screenshot (default: timestamped PNG).
# mount [mountpoint] ifuse-mount the app's Documents folder.
# unmount [mountpoint] fusermount -u. Aliases: umount, u.
# status Show device, app, and mount state.
# doctor Check which required/optional tools are installed.
#
# Global flags (before subcommand):
# -a, --app <bundle> Override app bundle for this call.
# -u, --udid <udid> Override device UDID.
# -y, --yes Skip the "not enough space" / rm confirmation prompts.
#
# Configuration precedence (highest wins):
# command-line flag > env var > ~/.config/ipad-util/config > built-in default
# Config file is shell-sourced; recognized keys: BUNDLE, UDID, MOUNTPOINT
# Env vars: IPAD_BUNDLE, IPAD_UDID, IPAD_MOUNTPOINT
set -euo pipefail
# --- config loading -----------------------------------------------------------
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/ipad-util/config"
if [ -f "$CONFIG_FILE" ]; then
# shellcheck disable=SC1090
. "$CONFIG_FILE"
fi
BUNDLE="${IPAD_BUNDLE:-${BUNDLE:-org.videolan.vlc-ios}}"
UDID_OVERRIDE="${IPAD_UDID:-${UDID:-}}"
DEFAULT_MOUNT_BASE="${IPAD_MOUNTPOINT:-${MOUNTPOINT:-}}"
# --- helpers ------------------------------------------------------------------
die() { echo "ipad-util: $*" >&2; exit 1; }
warn() { echo "ipad-util: $*" >&2; }
# Detect the system's package manager so install hints work on multiple distros.
_pm() {
if command -v dnf >/dev/null 2>&1; then echo dnf
elif command -v apt-get >/dev/null 2>&1; then echo apt
elif command -v pacman >/dev/null 2>&1; then echo pacman
elif command -v zypper >/dev/null 2>&1; then echo zypper
else echo ""
fi
}
# Return a distro-appropriate install command for a given tool.
install_hint() {
local tool="$1"
case "$(_pm):$tool" in
# --- Fedora / RHEL / Nobara (dnf) ---
dnf:afcclient|dnf:idevice_id|dnf:ideviceinfo|dnf:idevicescreenshot)
echo "sudo dnf install libimobiledevice" ;;
dnf:ifuse) echo "sudo dnf install ifuse" ;;
dnf:fusermount) echo "sudo dnf install fuse" ;;
dnf:ideviceinstaller) echo "not in Fedora repos — build from source: https://github.com/libimobiledevice/ideviceinstaller" ;;
dnf:numfmt) echo "sudo dnf install coreutils" ;;
dnf:jq) echo "sudo dnf install jq" ;;
# --- Debian / Ubuntu (apt) ---
apt:afcclient|apt:idevice_id|apt:ideviceinfo|apt:idevicescreenshot)
echo "sudo apt install libimobiledevice-utils" ;;
apt:ifuse) echo "sudo apt install ifuse" ;;
apt:fusermount) echo "sudo apt install fuse" ;;
apt:ideviceinstaller) echo "sudo apt install ideviceinstaller" ;;
apt:numfmt) echo "sudo apt install coreutils" ;;
apt:jq) echo "sudo apt install jq" ;;
# --- Arch / Manjaro (pacman) ---
pacman:afcclient|pacman:idevice_id|pacman:ideviceinfo|pacman:idevicescreenshot)
echo "sudo pacman -S libimobiledevice" ;;
pacman:ifuse) echo "AUR — yay -S ifuse (removed from official repos)" ;;
pacman:fusermount) echo "sudo pacman -S fuse2" ;;
pacman:ideviceinstaller) echo "sudo pacman -S ideviceinstaller" ;;
pacman:numfmt) echo "sudo pacman -S coreutils" ;;
pacman:jq) echo "sudo pacman -S jq" ;;
# --- openSUSE (zypper), best-effort ---
zypper:afcclient|zypper:idevice_id|zypper:ideviceinfo|zypper:idevicescreenshot)
echo "sudo zypper install libimobiledevice-tools" ;;
zypper:ifuse) echo "sudo zypper install ifuse" ;;
zypper:fusermount) echo "sudo zypper install fuse" ;;
zypper:ideviceinstaller) echo "sudo zypper install ideviceinstaller" ;;
zypper:numfmt) echo "sudo zypper install coreutils" ;;
zypper:jq) echo "sudo zypper install jq" ;;
*) echo "install '$tool' via your package manager" ;;
esac
}
need() {
command -v "$1" >/dev/null 2>&1 && return
die "missing tool: $1 ($(install_hint "$1"))"
}
# Non-fatal check used by `doctor`. Returns 0 if ok or optional-and-missing, 1 if required-and-missing.
_doctor_check() {
local tool="$1" purpose="$2" required="${3:-0}"
if command -v "$tool" >/dev/null 2>&1; then
printf " [ok] %-22s %s\n" "$tool" "$purpose"
return 0
fi
local hint; hint=$(install_hint "$tool")
if [ "$required" = "1" ]; then
printf " [FAIL] %-22s %s\n install: %s\n" "$tool" "$purpose" "$hint"
return 1
fi
printf " [skip] %-22s %s\n install: %s\n" "$tool" "$purpose" "$hint"
return 0
}
resolve_udid() {
if [ -n "$UDID_OVERRIDE" ]; then
echo "$UDID_OVERRIDE"
return
fi
local udids
mapfile -t udids < <(idevice_id -l 2>/dev/null)
case "${#udids[@]}" in
0) die "no iOS device detected (plug in and trust the computer)" ;;
1) echo "${udids[0]}" ;;
*) die "multiple devices detected; pass -u UDID or set IPAD_UDID. Found: ${udids[*]}" ;;
esac
}
afc() { afcclient -u "$(resolve_udid)" --documents "$BUNDLE" "$@"; }
info_key() { ideviceinfo -u "$(resolve_udid)" "$@" 2>/dev/null; }
mountpoint_default() {
if [ -n "$DEFAULT_MOUNT_BASE" ]; then
echo "$DEFAULT_MOUNT_BASE"
else
echo "/tmp/ipad-${BUNDLE##*.}"
fi
}
human_bytes() {
local n="${1:-0}"
# Apple reports storage in decimal (GB = 10^9), so use SI base to match what
# the user sees in Settings. Binary "GiB" output would be confusing here.
if command -v numfmt >/dev/null 2>&1; then
numfmt --to=si --suffix=B --format=%.2f "$n"
else
echo "${n} B"
fi
}
afc_size() { afc info "$1" 2>/dev/null | awk '/^st_size:/ {print $2; exit}'; }
afc_is_dir() {
afc info "$1" 2>/dev/null | grep -q "st_ifmt: S_IFDIR"
}
# afcclient `info` exits 0 even when the path doesn't exist, so check that
# real attributes are present in the output instead of relying on exit status.
afc_exists() { afc info "$1" 2>/dev/null | grep -q '^st_'; }
# Create a remote directory and any missing parents. afcclient mkdir is not recursive.
afc_mkdir_p() {
local path="$1"
[ -z "$path" ] && return
[ "$path" = "." ] && return
[ "$path" = "/" ] && return
afc_exists "$path" && return
afc_mkdir_p "$(dirname "$path")"
afc mkdir "$path" >/dev/null 2>&1 || true
}
# Recursively push a local directory to a remote path. afcclient's `put -r` is
# broken in some libimobiledevice versions, so we walk the tree ourselves.
put_tree() {
local src="$1" remote_base="$2"
afc_mkdir_p "$remote_base"
while IFS= read -r -d '' f; do
local rel="${f#$src/}"
local dest="$remote_base/$rel"
if [ -d "$f" ]; then
afc_mkdir_p "$dest"
else
echo " + $rel"
afc put "$f" "$dest"
fi
done < <(find "$src" -mindepth 1 -print0)
}
# Recursively pull a remote directory to a local path.
get_tree() {
local remote="$1" local_dir="$2"
mkdir -p "$local_dir"
local entry
while IFS= read -r entry; do
[ -z "$entry" ] && continue
local remote_path="$remote/$entry"
local local_path="$local_dir/$entry"
if afc_is_dir "$remote_path"; then
get_tree "$remote_path" "$local_path"
else
echo " > $entry"
afc get "$remote_path" "$local_path"
fi
done < <(afc ls "$remote" 2>/dev/null)
}
# Recursively delete a remote tree. afcclient rm is not recursive.
rm_tree() {
local path="$1"
if afc_is_dir "$path"; then
local entry
while IFS= read -r entry; do
[ -z "$entry" ] && continue
rm_tree "$path/$entry"
done < <(afc ls "$path" 2>/dev/null)
fi
afc rm "$path" >/dev/null 2>&1 || true
}
confirm() {
local prompt="$1" reply
if [ "${ASSUME_YES:-0}" = "1" ]; then return 0; fi
read -r -p "$prompt [y/N] " reply
[[ "$reply" =~ ^[Yy]$ ]]
}
# Sum bytes of a local file or directory tree.
local_size() {
local path="$1"
if [ -d "$path" ]; then
find "$path" -type f -printf '%s\n' 2>/dev/null | awk '{s+=$1} END {print s+0}'
elif [ -f "$path" ]; then
stat -c %s "$path"
else
echo 0
fi
}
# Sum bytes of a remote file or directory tree (one afc info per entry — slow on big trees).
remote_size() {
local path="$1"
if afc_is_dir "$path"; then
local entry sum=0 sz
while IFS= read -r entry; do
[ -z "$entry" ] && continue
sz=$(remote_size "$path/$entry")
sum=$((sum + sz))
done < <(afc ls "$path" 2>/dev/null)
echo "$sum"
else
afc_size "$path"
fi
}
# Currently-free bytes on the iOS device (matches what iPad Settings shows as free).
device_free() {
info_key -q com.apple.disk_usage -k AmountDataAvailable
}
# Free bytes on the local filesystem containing PATH.
path_free() {
local path="$1"
[ -e "$path" ] || path=$(dirname "$path")
df --output=avail -B 1 "$path" 2>/dev/null | awk 'NR==2 {gsub(/ /,""); print}'
}
# Pre-flight size check. Args: direction (put|get), transfer bytes, destination free bytes.
# Prompts on shortfall; bails out if the user says no.
preflight_size() {
local direction="$1" tx="$2" dst_free="$3"
[ "${tx:-0}" -gt 0 ] || return 0
local destlabel="device"
[ "$direction" = "get" ] && destlabel="local destination"
if [ -z "$dst_free" ] || [ "$dst_free" -le 0 ]; then
warn "could not determine $destlabel free space — skipping size check"
return 0
fi
printf "Transfer size: %s %s free: %s\n" \
"$(human_bytes "$tx")" "$destlabel" "$(human_bytes "$dst_free")"
if [ "$tx" -gt "$dst_free" ]; then
local shortfall=$((tx - dst_free))
warn "$(human_bytes "$shortfall") larger than free space on $destlabel"
if [ "${ASSUME_YES:-0}" = "1" ]; then
warn "proceeding anyway due to -y"
return 0
fi
confirm "Proceed anyway?" || die "transfer aborted"
fi
}
# --- subcommands --------------------------------------------------------------
cmd_put() {
[ "$#" -gt 0 ] || die "put: need at least one path"
local total=0 src sz
for src in "$@"; do
[ -e "$src" ] || continue
sz=$(local_size "$src")
total=$((total + sz))
done
preflight_size put "$total" "$(device_free)"
for src in "$@"; do
if [ ! -e "$src" ]; then
warn "'$src' not found — skipping"
continue
fi
local name; name=$(basename "$src")
if [ -d "$src" ]; then
echo ">> [dir] $src/ -> Documents/$name/"
put_tree "$src" "Documents/$name"
else
echo ">> [file] $src -> Documents/$name"
afc put "$src" "Documents/$name"
fi
done
}
cmd_get() {
[ "$#" -ge 1 ] || die "get: need remote path"
local remote="$1" local_path="${2:-$(basename "$1")}"
afc_exists "$remote" || die "get: remote path '$remote' not found"
echo " measuring remote size..."
local sz; sz=$(remote_size "$remote")
preflight_size get "$sz" "$(path_free "$local_path")"
if afc_is_dir "$remote"; then
echo ">> [dir] $remote/ -> $local_path/"
get_tree "$remote" "$local_path"
else
echo ">> [file] $remote -> $local_path"
afc get "$remote" "$local_path"
fi
}
cmd_ls() {
local target="${1:-Documents}"
afc ls "$target"
}
cmd_rm() {
local force=0
if [ "${1:-}" = "-f" ]; then force=1; shift; fi
[ "$#" -gt 0 ] || die "rm: need at least one remote path"
for path in "$@"; do
if ! afc_exists "$path"; then
warn "'$path' not found — skipping"
continue
fi
local kind="file"
afc_is_dir "$path" && kind="dir"
if [ "$force" -eq 0 ]; then
confirm "Delete $kind '$path'?" || { echo " skipped"; continue; }
fi
echo ">> rm $kind $path"
if [ "$kind" = "dir" ]; then
rm_tree "$path"
else
afc rm "$path"
fi
done
}
cmd_mv() {
[ "$#" -eq 2 ] || die "mv: need <old> <new>"
afc mv "$1" "$2"
echo "renamed: $1 -> $2"
}
cmd_mkdir() {
[ "$#" -eq 1 ] || die "mkdir: need <path>"
afc_mkdir_p "$1"
echo "created: $1"
}
cmd_sync() {
[ "$#" -eq 1 ] || die "sync: need one local directory"
local src="$1"
[ -d "$src" ] || die "sync: '$src' is not a directory"
local base; base=$(basename "$src")
local remote_dir="Documents/$base"
afc_mkdir_p "$remote_dir"
echo " planning sync (sizing changed files)..."
local plan_total=0 plan_count=0 lsz rsz
while IFS= read -r -d '' f; do
local rel="${f#$src/}"
local rp="$remote_dir/$rel"
lsz=$(stat -c %s "$f")
rsz=$(afc_size "$rp" || true)
if [ -z "$rsz" ] || [ "$rsz" != "$lsz" ]; then
plan_total=$((plan_total + lsz))
plan_count=$((plan_count + 1))
fi
done < <(find "$src" -type f -print0)
echo " $plan_count file(s) need transfer"
preflight_size put "$plan_total" "$(device_free)"
local pushed=0 skipped=0
while IFS= read -r -d '' local_file; do
local rel="${local_file#$src/}"
local remote_path="$remote_dir/$rel"
local local_sz remote_sz
local_sz=$(stat -c %s "$local_file")
remote_sz=$(afc_size "$remote_path" || true)
if [ -n "$remote_sz" ] && [ "$remote_sz" = "$local_sz" ]; then
skipped=$((skipped+1))
continue
fi
afc_mkdir_p "$(dirname "$remote_path")"
echo " + $rel"
afc put "$local_file" "$remote_path"
pushed=$((pushed+1))
done < <(find "$src" -type f -print0)
echo "sync done: $pushed pushed, $skipped already up-to-date"
}
cmd_info() {
need ideviceinfo
local udid; udid=$(resolve_udid)
local name class type version build total avail batt charging
name=$(info_key -k DeviceName)
class=$(info_key -k DeviceClass)
type=$(info_key -k ProductType)
version=$(info_key -k ProductVersion)
build=$(info_key -k BuildVersion)
total=$(info_key -q com.apple.disk_usage -k TotalDiskCapacity)
# AmountDataAvailable is the actually-free space; TotalDataAvailable counts
# purgeable caches as free, which doesn't match what iPad Settings shows.
avail=$(info_key -q com.apple.disk_usage -k AmountDataAvailable)
batt=$(info_key -q com.apple.mobile.battery -k BatteryCurrentCapacity 2>/dev/null || true)
charging=$(info_key -q com.apple.mobile.battery -k BatteryIsCharging 2>/dev/null || true)
echo "Name: $name"
echo "Model: $class ($type)"
echo "iOS: $version ($build)"
echo "UDID: $udid"
[ -n "$total" ] && echo "Storage: $(human_bytes "$avail") free of $(human_bytes "$total")"
if [ -n "$batt" ]; then
local cstr=""
[ "$charging" = "true" ] && cstr=" (charging)"
echo "Battery: ${batt}%${cstr}"
fi
echo "App: $BUNDLE"
}
cmd_space() {
need ideviceinfo
# Keys (in com.apple.disk_usage):
# TotalDiskCapacity full capacity (matches "256 GB" on the device spec)
# TotalDataCapacity storage available to user data (excludes iOS system reservation)
# AmountDataAvailable actually free right now (matches what Settings shows)
# TotalDataAvailable free + purgeable caches iOS can evict
local total data_cap free purgeable_free
total=$(info_key -q com.apple.disk_usage -k TotalDiskCapacity)
data_cap=$(info_key -q com.apple.disk_usage -k TotalDataCapacity)
free=$(info_key -q com.apple.disk_usage -k AmountDataAvailable)
purgeable_free=$(info_key -q com.apple.disk_usage -k TotalDataAvailable)
[ -n "$total" ] && [ -n "$data_cap" ] && [ -n "$free" ] || die "could not read storage info"
local user_used=$((data_cap - free))
local system=$((total - data_cap))
local purgeable=$((purgeable_free - free))
local pct=$(( user_used * 100 / total ))
printf "used: %s (your data)\n" "$(human_bytes "$user_used")"
printf "free: %s (immediately available)\n" "$(human_bytes "$free")"
printf "system: %s (iOS itself)\n" "$(human_bytes "$system")"
printf "total: %s\n" "$(human_bytes "$total")"
printf "%d%% used by your data\n" "$pct"
if [ "$purgeable" -gt 0 ]; then
printf "(plus %s of purgeable cache that iOS will evict if needed)\n" \
"$(human_bytes "$purgeable")"
fi
}
cmd_battery() {
need ideviceinfo
local batt charging
batt=$(info_key -q com.apple.mobile.battery -k BatteryCurrentCapacity)
charging=$(info_key -q com.apple.mobile.battery -k BatteryIsCharging)
[ -n "$batt" ] || die "could not read battery info"
local cstr=""
[ "$charging" = "true" ] && cstr=" (charging)"
echo "${batt}%${cstr}"
}
cmd_apps() {
if command -v ideviceinstaller >/dev/null 2>&1; then
local udid; udid=$(resolve_udid)
if ideviceinstaller -u "$udid" list -o list_user >/dev/null 2>&1; then
ideviceinstaller -u "$udid" list -o list_user
else
ideviceinstaller -u "$udid" -l -o list_user
fi
echo
echo "Test whether an app supports file sharing: ipad-util -a <bundle-id> ls"
return
fi
echo "ideviceinstaller is not installed — cannot list apps directly from the device."
echo " install: $(install_hint ideviceinstaller)"
echo
cat <<'EOF'
Common file-sharing-capable apps and their bundle IDs:
org.videolan.vlc-ios VLC
com.firecore.infuse Infuse
com.readdle.ReaddleDocsIPad Documents by Readdle
com.goodnotes.GoodNotes5 GoodNotes 5
org.xbmc.kodi Kodi
com.newin.nPlayerPlus nPlayer
com.skyjos.fileexplorer FE File Explorer
Use one with: ipad-util -a <bundle-id> <subcommand>
To find the bundle ID for any iOS app:
1. Open its App Store page in a browser and copy the numeric ID from the URL.
Example: https://apps.apple.com/us/app/vlc-for-mobile/id650377962 -> 650377962
2. Look up the bundle ID via Apple's iTunes API:
curl -s 'https://itunes.apple.com/lookup?id=<NUMERIC_ID>' | jq -r '.results[0].bundleId'
3. Test whether the app supports USB file sharing:
ipad-util -a <bundle-id> ls
If it lists files, the app opted into UIFileSharingEnabled and you can transfer to it.
If you get "Could not access documents directory", it doesn't.
EOF
}
cmd_screenshot() {
need idevicescreenshot
local out="${1:-screenshot-$(date +%Y%m%d-%H%M%S).png}"
idevicescreenshot -u "$(resolve_udid)" "$out"
echo "saved: $out"
}
cmd_mount() {
need ifuse
local mp="${1:-$(mountpoint_default)}"
mkdir -p "$mp"
if mountpoint -q "$mp" 2>/dev/null; then
echo "already mounted at $mp"
return 0
fi
local udid; udid=$(resolve_udid)
ifuse --documents "$BUNDLE" -u "$udid" "$mp"
echo "mounted: $mp (bundle=$BUNDLE udid=$udid)"
}
cmd_unmount() {
local mp="${1:-$(mountpoint_default)}"
if ! mountpoint -q "$mp" 2>/dev/null; then
echo "nothing mounted at $mp"
return 0
fi
fusermount -u "$mp"
echo "unmounted: $mp"
if [ "$mp" = "$(mountpoint_default)" ] && [ -d "$mp" ] && [ -z "$(ls -A "$mp" 2>/dev/null)" ]; then
rmdir "$mp" 2>/dev/null || true
fi
}
cmd_doctor() {
local ok=0
local pm; pm=$(_pm)
echo "Detected package manager: ${pm:-unknown}"
echo
echo "Required tools:"
_doctor_check afcclient "file transfer (put/get/ls/rm/...)" 1 || ok=1
_doctor_check idevice_id "device detection" 1 || ok=1
echo
echo "Optional tools:"
_doctor_check ideviceinfo "info, space, battery"
_doctor_check idevicescreenshot "screenshot"
_doctor_check ifuse "mount / unmount"
_doctor_check fusermount "unmount"
_doctor_check ideviceinstaller "apps (list installed apps)"
_doctor_check numfmt "human-readable sizes"
_doctor_check jq "bundle-id lookup in 'apps' help"
echo
echo "Connectivity:"
if command -v idevice_id >/dev/null 2>&1; then
local udids
mapfile -t udids < <(idevice_id -l 2>/dev/null)
if [ "${#udids[@]}" -eq 0 ]; then
echo " no device detected — plug in and tap 'Trust' on the iPad"
else
local u
for u in "${udids[@]}"; do echo " device: $u"; done
fi
else
echo " (cannot check — idevice_id missing)"
fi
echo
if [ "$ok" = "0" ]; then
echo "Status: ready"
else
echo "Status: missing required tools — see above"
exit 1
fi
}
cmd_status() {
echo "app: $BUNDLE"
local udids
mapfile -t udids < <(idevice_id -l 2>/dev/null)
if [ "${#udids[@]}" -eq 0 ]; then
echo "device(s): (none detected)"
else
echo "device(s): ${udids[*]}"
fi
local mp; mp=$(mountpoint_default)
if mountpoint -q "$mp" 2>/dev/null; then
echo "mount: $mp (active)"
else
echo "mount: $mp (inactive)"
fi
mount | awk '/fuse\.ifuse/ {print " also mounted: " $3}'
[ -f "$CONFIG_FILE" ] && echo "config: $CONFIG_FILE"
}
usage() {
sed -n '/^# ipad-util/,/^$/p' "$0" | sed -E 's/^# ?//' >&2
exit 2
}
# --- global flag parsing ------------------------------------------------------
while [ "$#" -gt 0 ]; do
case "$1" in
-a|--app) BUNDLE="$2"; shift 2 ;;
-u|--udid) UDID_OVERRIDE="$2"; shift 2 ;;
-y|--yes) ASSUME_YES=1; shift ;;
-h|--help|help) usage ;;
--) shift; break ;;
-*) die "unknown flag: $1 (try --help)" ;;
*) break ;;
esac
done
[ "$#" -ge 1 ] || usage
sub="$1"; shift
# Preflight: required tools must exist for any real subcommand. `doctor` and
# `help` are exempt so the user can still diagnose a broken install.
case "$sub" in
doctor|help|--help|-h) ;;
*)
command -v afcclient >/dev/null 2>&1 || die "missing required tool: afcclient (run 'ipad-util doctor' for details)"
command -v idevice_id >/dev/null 2>&1 || die "missing required tool: idevice_id (run 'ipad-util doctor' for details)"
;;
esac
case "$sub" in
put) cmd_put "$@" ;;
get) cmd_get "$@" ;;
ls) cmd_ls "$@" ;;
rm) cmd_rm "$@" ;;
mv) cmd_mv "$@" ;;
mkdir) cmd_mkdir "$@" ;;
sync) cmd_sync "$@" ;;
info) cmd_info ;;
space|df) cmd_space ;;
battery) cmd_battery ;;
apps) cmd_apps ;;
screenshot|shot) cmd_screenshot "$@" ;;
mount|m) cmd_mount "$@" ;;
unmount|umount|u) cmd_unmount "$@" ;;
status) cmd_status ;;
doctor) cmd_doctor ;;
*) die "unknown subcommand: $sub (try: --help)" ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment