Mobile File Access
TL;DR
CMDOP lets you browse, read, write, upload, and download files on iOS devices through the Python SDK. Access is sandboxed to Documents, Library, tmp, and Photos directories. Supports progress callbacks for large transfers, directory operations, and one-way or two-way sync patterns between local and mobile storage.
Access files on your iOS deviceโs sandboxed storage.
What does the iOS file system structure look like?
marks-iphone:/
โโโ Documents/ # User documents (read/write)
โ โโโ notes.txt
โ โโโ data.sqlite
โ โโโ reports/
โ
โโโ Library/ # App data (read/write)
โ โโโ Caches/
โ โโโ Preferences/
โ โโโ Application Support/
โ
โโโ tmp/ # Temporary files (read/write)
โ
โโโ Photos/ # Photo library (read only)
โโโ IMG_0001.jpg
โโโ IMG_0002.jpg
โโโ ...How do I list files on an iOS device?
from cmdop import AsyncCMDOPClient
# Open a remote client session with your API key
async with AsyncCMDOPClient.remote(api_key="cmd_xxx") as client:
# List all files and subdirectories inside /Documents
docs = await client.files.list("marks-iphone", "/Documents")
# Print each file's name and size
for doc in docs:
print(f"{doc.name} - {doc.size} bytes")How do I read files on an iOS device?
# Read a text file and return its contents as a string
content = await client.files.read("marks-iphone", "/Documents/notes.txt")
print(content)
# Read a binary file (e.g., SQLite database) and return raw bytes
data = await client.files.read_bytes("marks-iphone", "/Documents/data.sqlite")How do I write files to an iOS device?
# Write a JSON string as a text file on the device
await client.files.write(
"marks-iphone",
"/Documents/config.json",
'{"key": "value"}'
)
# Read a local binary file and write its bytes to the device
with open("./local_file.db", "rb") as f:
data = f.read()
await client.files.write_bytes(
"marks-iphone",
"/Documents/database.db",
data
)How do I download files from an iOS device?
# Download a single file from the device to a local path
await client.files.download(
"marks-iphone",
"/Documents/report.pdf",
"./report.pdf"
)
# Define a progress callback to track download completion
def on_progress(downloaded, total):
percent = (downloaded / total) * 100
print(f"Progress: {percent:.1f}%")
# Download a large file with real-time progress reporting
await client.files.download(
"marks-iphone",
"/Documents/large_file.zip",
"./large_file.zip",
on_progress=on_progress
)How do I upload files to an iOS device?
# Upload a single local file to the device's Documents folder
await client.files.upload(
"./document.pdf",
"marks-iphone",
"/Documents/document.pdf"
)
# Upload multiple files in a loop
files = ["file1.txt", "file2.txt", "file3.txt"]
for file in files:
await client.files.upload(
f"./{file}",
"marks-iphone",
f"/Documents/{file}"
)How do I access the iOS photo library?
Access requires user permission in the iOS app.
# List all photos (requires photo-library permission granted in the app)
photos = await client.files.list("marks-iphone", "/Photos")
print(f"Total photos: {len(photos)}")
# Download a specific photo by filename
await client.files.download(
"marks-iphone",
"/Photos/IMG_1234.jpg",
"./photo.jpg"
)
# Download every photo for a full backup
for photo in photos:
await client.files.download(
"marks-iphone",
photo.path,
f"./backup/{photo.name}"
)How do I get photo metadata?
# Retrieve metadata (size, timestamps) for a specific photo
info = await client.files.info("marks-iphone", "/Photos/IMG_1234.jpg")
print(f"Size: {info.size} bytes")
print(f"Created: {info.created_at}")
print(f"Modified: {info.modified_at}")How do I perform directory operations on an iOS device?
# Create a nested directory structure on the device
await client.files.mkdir("marks-iphone", "/Documents/reports/2024")
# Delete a single file from the device
await client.files.delete("marks-iphone", "/Documents/old_file.txt")
# Recursively delete a directory and all its contents
await client.files.delete(
"marks-iphone",
"/Documents/old_folder",
recursive=True
)
# Move (rename) a file within the device sandbox
await client.files.move(
"marks-iphone",
"/Documents/draft.txt",
"/Documents/final.txt"
)
# Copy a file to a new location on the device
await client.files.copy(
"marks-iphone",
"/Documents/template.txt",
"/Documents/new_document.txt"
)How do I sync files between local and mobile?
How do I sync files from local to mobile (one-way)?
import os
async def sync_to_mobile(local_dir: str, remote_dir: str):
"""Upload new or changed files to mobile."""
# Build a map of local filenames to their last-modified timestamps
local_files = {f: os.path.getmtime(os.path.join(local_dir, f))
for f in os.listdir(local_dir)}
# Fetch the list of files already on the device
remote_files = await client.files.list("marks-iphone", remote_dir)
remote_map = {f.name: f.modified_at.timestamp() for f in remote_files}
# Upload files that are new or newer locally than on the device
for name, mtime in local_files.items():
if name not in remote_map or mtime > remote_map[name]:
print(f"Uploading: {name}")
await client.files.upload(
os.path.join(local_dir, name),
"marks-iphone",
f"{remote_dir}/{name}"
)
await sync_to_mobile("./docs", "/Documents")How do I sync files from mobile to local (one-way)?
async def sync_from_mobile(remote_dir: str, local_dir: str):
"""Download new or changed files from mobile."""
# List all files on the device in the given directory
remote_files = await client.files.list("marks-iphone", remote_dir)
for remote_file in remote_files:
local_path = os.path.join(local_dir, remote_file.name)
# Download if the file is missing locally or outdated
should_download = (
not os.path.exists(local_path) or
remote_file.modified_at.timestamp() > os.path.getmtime(local_path)
)
if should_download:
print(f"Downloading: {remote_file.name}")
await client.files.download(
"marks-iphone",
remote_file.path,
local_path
)
await sync_from_mobile("/Documents", "./backup")How do I set up two-way sync between local and mobile?
async def two_way_sync(local_dir: str, remote_dir: str):
"""Sync both directions, newer wins."""
# Build a map of local filenames to their modification times
local_files = {}
for name in os.listdir(local_dir):
path = os.path.join(local_dir, name)
local_files[name] = os.path.getmtime(path)
# Fetch remote file list and index by name
remote_files = await client.files.list("marks-iphone", remote_dir)
remote_map = {f.name: f for f in remote_files}
# Union of all filenames from both local and remote
all_files = set(local_files.keys()) | set(remote_map.keys())
for name in all_files:
local_path = os.path.join(local_dir, name)
remote_path = f"{remote_dir}/{name}"
local_mtime = local_files.get(name, 0)
remote_mtime = remote_map.get(name, None)
remote_mtime = remote_mtime.modified_at.timestamp() if remote_mtime else 0
# Upload or download depending on which side has the newer version
if local_mtime > remote_mtime:
print(f"Upload: {name}")
await client.files.upload(local_path, "marks-iphone", remote_path)
elif remote_mtime > local_mtime:
print(f"Download: {name}")
await client.files.download("marks-iphone", remote_path, local_path)Error Handling
from cmdop.exceptions import (
FileNotFoundError,
PermissionError,
StorageFullError,
DeviceOfflineError
)
# Wrap file operations in try/except to handle common failure modes
try:
await client.files.read("marks-iphone", "/Documents/file.txt")
except FileNotFoundError:
print("File doesn't exist")
except PermissionError:
print("No access to this location")
except StorageFullError:
print("Device storage is full")
except DeviceOfflineError:
print("Device not connected")What are the mobile file access limitations?
What paths can I access in the iOS sandbox?
Can only access:
/Documents- App documents/Library- App library/tmp- Temporary files/Photos- Photo library (read-only)
Cannot access:
- System files
- Other app data
- System settings
What are the photo library restrictions?
- Read-only access
- Requires user permission
- Canโt delete photos via API
What should I know about large file transfers?
- Consider chunked transfer for large files
- Watch for storage limits
- Background transfers may be interrupted
Next
Last updated on