从备份磁碟向手机中恢复照片,但速度太慢或卡死

问题描述

已知手机和电脑用的是 USB3.0 的数据线连接,读写速度至少也应该是 5MB/s, 即受限于手机内存的读写速度限制。

然后博主昨天在 Windows11 从备份往回写 60GB 的备份照片的时候就觉得很慢,耗时五小时还有一半没有传完,于是拔掉数据线走人。

第二天再传,想着 Windows 反正能够选择跳过所有重名文件,直接断点续传就行,但是没想到只要选择跳过所有,整个传输进程就会被卡退。

为什么呢?试试 Linux!

起初以为是 Windows 的 BUG, 那就换 Ubuntu 来复制呗,反正双系统,哪个行上哪个…. 结果坏了,Ubuntu 没有 kill 掉我的传输进程,而是直接整个卡死,断点重启后,/dev/nvme0n1p6 还出现脏位,boot 失败进了 emergency terminal.

后来一想,想来手机的文件系统挂载在 Linux 上肯定是比较脆弱的,估计这么多照片文件没有合适的索引来查询,导致比对重名文件的时候直接跑满 CPU 爆掉了。

那就手动提取

其实也不用索引,本身文件名在没有特殊字符的时候就是可以有序排列的,那我们写一个脚本,将 source folder 和 target fodler 中的文件列出来,各自排好序,比对出缺少的文件,再循环 cp 他们不就行了?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash

SOURCE_DIR="/media/sieni/Extra_Data/pivot_backup/Photos-ONP10P/2025.12.25/DCIM/Camera"
TARGET_DIR="/run/user/1000/gvfs/gphoto2:host=OnePlus_WAIPIO-MTP__SN%3A60D8788C_60d8788c/DCIM/Camera"
OUTPUT_TXT="/media/sieni/Extra_Data/pivot_backup/Photos-ONP10P/2025.12.25/missing_files.txt"

TMP_SOURCE_LIST="/tmp/source_files.txt"
TMP_TARGET_LIST="/tmp/target_files.txt"

# List filenames in source directory
ls "$SOURCE_DIR" | sort > "$TMP_SOURCE_LIST"

# List filenames in target directory
ls "$TARGET_DIR" | sort > "$TMP_TARGET_LIST"

# Find files that are in source but not in target
comm -23 "$TMP_SOURCE_LIST" "$TMP_TARGET_LIST" > "$OUTPUT_TXT"

TOTAL_FILES=$(wc -l < "$OUTPUT_TXT")
CURRENT=0

echo "Total files to copy: $TOTAL_FILES"

while read -r filename; do
CURRENT=$((CURRENT + 1))
PERCENT=$((CURRENT * 100 / TOTAL_FILES))

echo "[$CURRENT/$TOTAL_FILES] ($PERCENT%) Copying: $filename"

cp "$SOURCE_DIR/$filename" "$TARGET_DIR/"

done < "$OUTPUT_TXT"

# Clean up temporary files
rm "$TMP_SOURCE_LIST" "$TMP_TARGET_LIST"

echo "Finished copying missing files."

成功了,完美将手机存储上的负担降到最轻,一次 ls 就弄清缺少的文件,接下来都是单线程逐个 cp.

传输要个半个小时,于是就有了这篇博客,分享经验,留住感动。

还有后续?时间戳有的不对!

传输完成后,为什么 Today 时间下一大堆图片和视频? 除了本机自带相机拍摄的照片,即元数据中明确写入拍摄时间的。

想要用 rsync 命令同步时间戳,但是被拒绝。

对了,我不是 Android 吗,为什么不用 Google 提供的底层通讯 adb 呢?毕竟我们一直在通讯的 gvfs-gphoto2 是一个不稳定的中间层。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash

SOURCE_DIR="/media/sieni/Extra_Data/pivot_backup/Photos-ONP10P/2025.12.25/DCIM/Camera"
TARGET_DIR="/sdcard/DCIM/Camera"
OUTPUT_TXT="/media/sieni/Extra_Data/pivot_backup/aPhotos-ONP10P/2025.12.25/missing_files.txt"

adb shell ls "$TARGET_DIR" | tr -d '\r' | sort > /tmp/target_files.txt

ls "$SOURCE_DIR" | sort > /tmp/source_files.txt

comm -23 /tmp/source_files.txt /tmp/target_files.txt > "$OUTPUT_TXT"

TOTAL_FILES=$(wc -l < "$OUTPUT_TXT")
CURRENT=0

echo "Total files to copy via ADB: $TOTAL_FILES"

while read -r filename; do
[ -z "$filename" ] && continue
CURRENT=$((CURRENT + 1))
PERCENT=$((CURRENT * 100 / TOTAL_FILES))

echo "[$CURRENT/$TOTAL_FILES] ($PERCENT%) Pushing: $filename"
adb push "$SOURCE_DIR/$filename" "$TARGET_DIR/"

done < "$OUTPUT_TXT"

adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "file://$TARGET_DIR"

echo "Finished."

瞬间传完,并且一点问题都没有,彻底解决,对了,弄完这一套才想起来是不是用市面上的手机助手会更方便呢?


从备份磁碟向手机中恢复照片,但速度太慢或卡死
http://example.com/2026/01/07/copy-photos-to-phone/
作者
Sieni Wei
发布于
2026年1月7日
许可协议