问题描述
已知手机和电脑用的是 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"
ls "$SOURCE_DIR" | sort > "$TMP_SOURCE_LIST"
ls "$TARGET_DIR" | sort > "$TMP_TARGET_LIST"
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"
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."
|
瞬间传完,并且一点问题都没有,彻底解决,对了,弄完这一套才想起来是不是用市面上的手机助手会更方便呢?