Skip to Content

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