Skip to content

Instantly share code, notes, and snippets.

@L1ghtmann
Last active December 4, 2025 05:05
Show Gist options
  • Select an option

  • Save L1ghtmann/c4d287a5f00d16f0e3bfae3bbadf1808 to your computer and use it in GitHub Desktop.

Select an option

Save L1ghtmann/c4d287a5f00d16f0e3bfae3bbadf1808 to your computer and use it in GitHub Desktop.
Mount iDevice on Win and copy photos/videos off
#!/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