![大规模迁移 EXIF GPS 数据(又名逃离 iPhoto)](https://linux22.com/image/1361688/%E5%A4%A7%E8%A7%84%E6%A8%A1%E8%BF%81%E7%A7%BB%20EXIF%20GPS%20%E6%95%B0%E6%8D%AE%EF%BC%88%E5%8F%88%E5%90%8D%E9%80%83%E7%A6%BB%20iPhoto%EF%BC%89.png)
我正在尝试将我的照片库(超过 12000 张)移出 iPhoto 以用于 Adobe Lightroom,并希望使用 iPhoto 的应用内功能将我添加到照片中的 GPS 数据包含在内(此数据存储在 Apple 的专有数据库中,而不是照片本身的元数据)。我可以通过导出来传输数据,但我想要 iPhoto 不会修改的原始 RAW 文件。所以我提出的解决方案是:
1) 将所有原始 RAW 照片导出到按事件名称排序的目录树中。2) 将所有照片导出为 JPEG,并将 GPS 数据嵌入 EXIF 数据中(iPhoto 可以做到)。3) 使用“exiftool”从 jpeg 中提取 GPS 数据并将其复制到匹配的原始文件中。
我可以使用以下命令一次对一张照片进行 #3 操作:
exiftool -overwrite_original_in_place -tagsFromFile ~/Photos-Mod/Event001/photo001.jpg -gps:all ~/Photos-Orig/Event001/photo001.NEF
Photos-Mod 文件包含来自 iPhoto 的 GPS 数据,而 Photos-Orig 没有。除了主目录名称和文件扩展名外,目录树和文件名将完全相同(在某些情况下,我的原始文件也是 jpeg)。我希望有一个好方法可以编写一个脚本,可以在 Photos-Mod 父目录中的 iPhoto 修改文件上运行 exiftool,并将 GPS 数据移动到 Photos-Orig 父目录中匹配文件名和事件目录的原始文件。
我只是没有编写脚本的技能。任何帮助都非常感谢。
答案1
该问题由以下几个部分组成:
- 查找
Photos-Mod
目录下的所有照片 - 找到下方的每一张对应的照片
Photos-Orig
exiftools
使用正确的参数调用
查找所有照片
通过使用像这样的 glob 表达式,这很容易~/Photo-Mod/*/*
。
找到对应的照片
给定一个完整路径,我们可以用 替换Photo-Mod
。Photo-Orig
我们进一步将文件扩展名更改为 ,*
以便我们有另一个 glob 表达式。如果此 glob 不匹配任何文件,我们将打印一条错误消息,但只需继续即可。
现在调用 exiftools 很容易。
Bash 解决方案
快速回顾一下 Bash 语法:
Foreach 循环:
for variable in EXPR; do COMMANDS; done
如果别的:
if COND; then COMMANDS; else COMMANDS; fi
Filetests:(
[ -e $file ]
测试-e
文件是否存在)变量赋值:
var=$(COMMANDS)
。
我们可以通过使用正则表达式sed
。
# There are probably more elegant ways, but I don't know much bash
for mod in ~/Photo-Mod/*/*/*; do
orig=$(echo $mod | sed -e 's/Photo-Mod/Photo-Orig/;s/\.[^.]*$/.*/');
orig=($orig); # Apply the glob expression, select result
if [ -e $orig ]; then
exiftool -overwrite_original_in_place -tagsFromFile "$mod" -gps:all "$orig";
else
echo "No corresponding file for $mod found. Skipping!" >&2;
fi;
done
删除所有换行符后即可直接在命令行上运行。您还可以将其放入 shell 脚本中,然后从那里调用它。
(笔记:使用类似的 glob 表达式进行测试,并且exiftools
在 GNU bash 下没有进行测试)
Perl 解决方案
Perl 语法快速介绍:
Foreach 循环:
for my $variable (LIST) { COMMANDS }
如果别的:
if (COND) { COMMANDS } else { COMMANDS }
文件测试:
-e $filename
变量赋值:
my $var = EXPR;
正则表达式是语言的一部分,可以通过 来应用$var =~ /REGEX/
。
use strict; use warnings; # helps us write better scripts
use autodie; # automatic error handling
for my $mod (glob '~/Photo-Mod/*/*/*') {
my $orig = $mod;
$orig =~ s/Photo-Mod/Photo-Orig/;
$orig =~ s/\.[^.]*$/.*/;
if (($orig) = glob qq("$orig")) { # implicitly tests for existence
system 'exiftool', '-overwrite_original_in_place',
'-tagsFromFile', $mod, '-gps:all', $orig;
} else {
warn "No corresponding file for $mod found. Skipping!\n";
}
}
您可以将代码转储到文件中,然后使用 调用它perl script.pl
。或者您可以使用此处的文档:
$ perl <<'END'
# The code goes here
END
(笔记:Perl 脚本已在 Linux 上使用 perls v16.3 和 v14.2 进行了测试。)