Last active
December 4, 2025 05:05
-
-
Save L1ghtmann/c4d287a5f00d16f0e3bfae3bbadf1808 to your computer and use it in GitHub Desktop.
Mount iDevice on Win and copy photos/videos off
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| src="$HOME/iP" | |
| target="$HOME/iPhotos" | |
| if ! [[ -f /tmp/.s1 ]]; then | |
| # There are a few of these commands that must be run first | |
| # Relies on WSL+https://github.com/dorssel/usbipd-win | |
| echo ' | |
| Please run the following in Powershell (Admin) and then restart your PC: | |
| $busid = usbipd list | Select-String "05ac" | ForEach-Object { ($_ -split "\s+")[0] } | |
| usbipd bind --force --busid $busid | |
| ' | |
| touch /tmp/.s1 | |
| exit 0 | |
| fi | |
| if ! [[ -f /tmp/.s2 ]]; then | |
| echo ' | |
| Please open a WSL instance and separately run the following in Powershell: | |
| $busid = usbipd list | Select-String "05ac" | ForEach-Object { ($_ -split "\s+")[0] } | |
| usbipd attach --wsl --busid $busid | |
| ' | |
| touch /tmp/.s2 | |
| exit 0 | |
| fi | |
| if ! command -v "lsusb" >/dev/null 2>&1; then | |
| echo "Installing usbutils" | |
| sudo apt install usbutils -y | |
| fi | |
| # Check for successful passthrough | |
| if [[ -z $(lsusb | grep Apple) ]]; then | |
| echo "Error: no Apple Device found in lsusb. Exiting."; exit 1 | |
| fi | |
| # Check for tooling | |
| if [[ -z $(echo $PATH | grep /usr/local/bin) ]]; then | |
| echo "PATH='$PATH':/usr/local/bin" >> ~/.profile | |
| source ~/.profile | |
| fi | |
| tools=(idevice_id idevicepair usbmuxd ifuse) | |
| for tool in "${tools[@]}"; do | |
| if ! command -v "$tool" >/dev/null 2>&1; then | |
| echo "$tool is NOT installed." | |
| echo "Installing build tools" | |
| sudo apt install build-essential git pkg-config libusb-1.0-0-dev libplist-dev libssl-dev libtool autoconf automake libcurl4-openssl-dev fuse libfuse3-dev rsync -y | |
| if [[ $tool == idevice_id || $tool == idevicepair ]]; then | |
| repos=(libimobiledevice-glue libusbmuxd libtatsu libimobiledevice) | |
| for repo in "${repos[@]}"; do | |
| if ! [[ -d $repo ]]; then | |
| git clone --depth=1 --recursive "https://github.com/libimobiledevice/$repo" | |
| fi | |
| done | |
| for repo in "${repos[@]}"; do | |
| pushd "$repo" && echo "Building $repo..." || (echo "$repo DNE!"; exit 2) | |
| ./autogen.sh || (echo "Autogen failed."; exit 3) | |
| make -j"$(nproc --all)" || (echo "Make failed."; exit 4) | |
| sudo make install -j"$(nproc --all)" || (echo "Make install failed."; exit 5) | |
| popd | |
| # else won't find -glue.so.0 | |
| sudo ldconfig | |
| done | |
| else | |
| if ! [[ -d $tool ]]; then | |
| git clone --depth=1 --recursive "https://github.com/libimobiledevice/$tool" | |
| fi | |
| pushd "$tool" && echo "Building $tool..." || (echo "$tool DNE!"; exit 2) | |
| ./autogen.sh || (echo "Autogen failed."; exit 3) | |
| make -j"$(nproc --all)" || (echo "Make failed."; exit 4) | |
| sudo make install -j"$(nproc --all)" || (echo "Make install failed."; exit 5) | |
| popd | |
| fi | |
| fi | |
| done | |
| # Fix stale usbmuxd | |
| sudo pkill usbmuxd | |
| # run in background | |
| sudo usbmuxd & | |
| pid=$! | |
| sleep 5 | |
| # May need to re-run the script if this fails the first time | |
| if [[ -z "$(idevice_id -l)" ]]; then | |
| echo "idevice_id error. Exiting"; exit 6 | |
| fi | |
| idevicepair pair || (echo "idevicepair failed. Exiting."; exit 7) | |
| sleep 5 | |
| mkdir -pv $src $target | |
| count=$(ls $target | wc -l) | |
| ifuse $src || (echo "ifuse failed. Exiting."; exit 8) | |
| # wait for 30s or a couple of min for population (find ~/iP/DCIM -type f | wc -l should read same number) | |
| sleep 30 | |
| # copy | |
| rsync -av --progress --ignore-existing "$src/DCIM/" "$target/" | |
| # move out of folders | |
| find $target -mindepth 2 -type f -exec mv -v -t $target {} + | |
| find $target -type d -empty -delete | |
| pcount=$(ls $target | wc -l) | |
| if [[ $pcount > $count ]]; then | |
| echo "Have $pcount photos in $target" | |
| else | |
| echo "Copying failed" | |
| fi | |
| fusermount -u $src || (echo "fusermount failed"; exit 9) | |
| kill $pid || (echo "usbmuxd still running?"; exit 10) | |
| rm /tmp/{.s1,.s2} | |
| echo ' | |
| Please run the following from Powershell (Admin) to complete operation: | |
| $busid = usbipd list | Select-String "05ac" | ForEach-Object { ($_ -split "\s+")[0] } | |
| usbipd detach --busid $busid | |
| usbipd unbind --busid $busid | |
| ' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment