增量备份手机照片的方法

背景是 我在android手机上 /sdcard/DCIM/Camera 中有一些照片;

在mac-os上也有一些照片 /Volumes/XXXX DISK/picture/phone_a

这两个目录有大部分照片的文件名都是一样的。

使用adb pull,只拷贝手机比电脑多的照片作为备份。

可以这样做:

sh 复制代码
#!/bin/bash

PHONE_DIR="/sdcard/DCIM/Camera"
MAC_DIR="/Volumes/XXXX DISK/picture/phone_a"

TMP_PHONE="/tmp/phone_files.txt"
TMP_MAC="/tmp/mac_files.txt"
TMP_COPY="/tmp/to_copy.txt"

adb shell "ls \"$PHONE_DIR\"" | sort > "$TMP_PHONE"
ls "$MAC_DIR" | sort > "$TMP_MAC"

comm -23 "$TMP_PHONE" "$TMP_MAC" > "$TMP_COPY"

if [[ ! -s "$TMP_COPY" ]]; then
    echo "--- done ---"
    exit 0
fi


echo "--- start copy ---"

echo "File size:"
cat $TMP_COPY | wc -l

while IFS= read -r filename; do
    echo "copying: $PHONE_DIR/$filename -> $MAC_DIR"
    adb pull "$PHONE_DIR/$filename" "$MAC_DIR"
done < "$TMP_COPY"

rm -f "$TMP_PHONE" "$TMP_MAC" "$TMP_COPY"

echo "--- done ---"

工作原理:

  1. 使用adb shell ls获取手机文件列表
  2. 使用ls获取电脑文件列表
  3. 用comm命令比较差异(-23参数显示只在第一个文件中存在的内容)
  4. 循环调用adb pull复制差异文件

mac上的 comm 指令用法

comm 是一个用于逐行比较两个已排序文件的 Linux/Unix 命令。它特别适合比较文件名列表,因为它能高效地识别出文件之间的差异。下面详细解释 comm -23 的工作原理:

基本输出格式

comm 命令默认输出三列结果:

  1. 第一列:只在第一个文件中出现的行
  2. 第二列:只在第二个文件中出现的行
  3. 第三列:在两个文件中都出现的行

例如:

bash 复制代码
$ comm file1 file2
a
    b
        c
d

选项参数

-1-2-3 选项用于抑制对应的输出列:

  • -1:隐藏第一列(只存在于第一个文件的行)
  • -2:隐藏第二列(只存在于第二个文件的行)
  • -3:隐藏第三列(共同存在的行)

comm -23 详解

comm -23 file1 file2 表示:

  • -2:隐藏第二列(只存在于第二个文件的行)
  • -3:隐藏第三列(共同存在的行)
  • 只保留第一列:即只存在于第一个文件中的行

在照片同步脚本中的应用

在你的脚本中:

bash 复制代码
comm -23 "$TMP_PHONE" "$TMP_MAC" > "$TMP_COPY"
  • $TMP_PHONE:手机中的文件列表(第一个文件)
  • $TMP_MAC:电脑中的文件列表(第二个文件)
  • 结果:只输出手机中有但电脑中没有的文件名

工作流程示例

假设:

  • 手机文件:a.jpg, b.jpg, c.jpg
  • 电脑文件:a.jpg, c.jpg, d.jpg

执行过程:

  1. 排序后的文件:

    bash 复制代码
    # phone_files.txt
    a.jpg
    b.jpg
    c.jpg
    
    # mac_files.txt
    a.jpg
    c.jpg
    d.jpg
  2. comm -23 比较结果:

    复制代码
    b.jpg
  3. 最终只复制 b.jpg

重要前提

comm 命令要求输入文件必须是:

  1. 已排序 :使用 sort 命令预处理
  2. 无重复项:每个文件名唯一
  3. 格式一致:相同的行尾格式(Unix LF)

与其他命令对比

命令 特点 适用场景
comm 需要排序输入,输出格式化 比较两个已排序列表
diff 不需要预排序,输出变更详情 比较文件内容差异
grep -F 逐行查找,不需要排序 小文件或简单查找
awk 灵活处理,可处理未排序文件 复杂比较或需要额外处理时

实际应用技巧

  1. 处理特殊字符

    bash 复制代码
    # 使用 -b 忽略尾随空格
    comm -23 -b <(adb shell ls "$PHONE_DIR" | sort) <(ls "$MAC_DIR" | sort)
  2. 大小写敏感

    bash 复制代码
    # 使用 -i 忽略大小写
    comm -23 -i file1 file2
  3. 检查共同文件

    bash 复制代码
    # 只显示共同文件(第三列)
    comm -12 file1 file2

在你的照片同步场景中,comm -23 是最佳选择,因为它:

  1. 高效处理大量文件
  2. 精确输出差异文件
  3. 资源消耗低(相比循环比较)
  4. 直接生成可操作的列表

理解 comm 命令能帮助你更好地处理文件比较任务,特别是在需要高效同步文件的场景中。