求批量删除特定照片的 shell 脚本

2020-02-24 01:09:43 +08:00
 kiev84

原因是这样的: 本人是摄影爱好者,因为拍摄时要兼顾出图速度和质量,因此相机设置为同时拍 raw 和 jpg,硬盘里有大量的照片,大部分是 raw (扩展名有 cr2,arw,raf,nef,dng ),一般也会有同名的 jpg 图像。 现在因为硬盘空间吃紧,计划删除 jpg 图片。因为只要有 raw 文件,需要时可以随时生成 jpg. 本来直接搜索 jpg 删除就可以了,但是问题来了。

本人学习摄影的早期,以及后来有时候因为相机设置作物,有时拍的照片只有 jpg,没有同名的 raw,如果直接搜索删除所有 jpg,可能一些不该删除的照片也会丢失。 因此请各位大神帮助,看看能不能有一个脚本,按照下面的条件删除:


搜索文件夹及其子文件夹(共有三层、按照年月日的层级),删除有同名 raw (具体扩展名为 cr2,arw,raf,nef,dng)文件的 jpg,保留没有同名 raw 文件的 jpg.


非常非常感谢!

2041 次点击
所在节点    问与答
8 条回复
CEBBCAT
2020-02-24 02:14:14 +08:00
逻辑非常清晰,我想明天试试写一个,但害怕出了问题追悔莫及。楼主有做备份吗?

Google Photos 提供近乎没有压缩的无限备份
wtks1
2020-02-24 02:23:57 +08:00
不计较速度的话,写起来应该不麻烦,脚本先遍历一遍,把所有 raw 的文件名都储存在 sqlite 的表里,然后再遍历 jpg,每一个文件都拿到数据库里查询一下,存在就删除,不存在就保留
zhzy
2020-02-24 02:27:44 +08:00
一个建议:不要直接删除,把不要的照片按原来的路径重命名( y-m-d-文件名)然后移动到一个单独的文件夹里,随便找个地方备份冷存就行了,然后过一段时间确认真的不要了再删掉
xiofee
2020-02-24 03:37:28 +08:00
在当前目录下查找同名 jpg 文件并重命名后缀名为 jpg.bak

windows
@for /r %i in (*.cr2;*.arw;*.raf;*.nef;*.dng) do @if exist "%~dpni.jpg". rename "%~dpni.jpg" "%~ni.jpg.bak"

linux
find `pwd` -regextype posix-extended -regex '.*\.(cr2|arw|raf|nef|dng)$' -exec sh -c 'test -f "${@%.*}.jpg" && mv "${@%.*}.jpg" "${@%.*}.jpg.bak"' sh {} ';'

mac
find -E `pwd` -regex '.*\.(cr2|arw|raf|nef|dng)$' -exec sh -c 'test -f "${@%.*}.jpg" && mv "${@%.*}.jpg" "${@%.*}.jpg.bak"' sh {} ';'

我觉得这些重要的东西还是手工筛选比较放心点。。。
mcfog
2020-02-24 03:39:44 +08:00
列出 raw 文件: find -name *.raw . (我可能写错,自己 man find) 或 ls | grep . raw
遍历: xargs,或者 find 自带
raw 后缀名替换 jpg: sed
假删除(测试): echo
真删除: mv <filename> /tmp
ETiV
2020-02-24 05:39:36 +08:00
很简单直观的写法:
找到 jpg 文件,并且替换末尾扩展名为 raw 格式的,然后再测试 raw 文件是否存在

```$ cat check-raw.sh
#!/bin/bash

jpg="$1"

for ext_name in cr2 arw raf nef dng; do
raw_name=$(echo "${jpg}" | sed -E "s;\.jpg\$;.${ext_name};g")
if [[ -e "${raw_name}" ]]; then
echo delete "${jpg}", because found "${raw_name}"
mv "${jpg}" "${jpg}.bak"
exit
fi
done

echo keeping "${jpg}"

```

把上面内容保存为 check-raw.sh

在同级目录运行
find ${相册目录} -type f -name '*.jpg' -print0 | xargs -0 -n 1 bash ./check-raw.sh
ps1aniuge
2020-02-24 16:07:21 +08:00
$你的目录 = 'a:\pscode'
$所有扩展名 = 'cr2',',arw','raf','nef','dng'

$所有文件 = Get-ChildItem -Path $你的目录 -Include '*.jpg' -File -Recurse
foreach ($temp in $所有文件)
{
$temp1 = $temp.fullname.substring(0,($temp.fullname.Length -3))
foreach ($当前扩展名 in $所有扩展名)
{
$temp2 = $temp1 + $当前扩展名
if (Test-Path -LiteralPath $temp2)
{

}
else
{
$i++
}
}

if ($i -lt $所有扩展名.Length)
{
Write-Warning ("文件 [{0}] 将被删除" -f $temp.fullname )
#Remove-Item -LiteralPath $temp.fullname
}
$i = 0
}

------------------------------
win,linux,通用的 powershell 脚本。调试通过。
文件保存时加上 bom 头。
$你的目录,,,,,指向你的目录
#Remove-Item ,,,,去掉前面的井号,即可真正删除文件。
ps1aniuge
2020-02-24 16:15:17 +08:00
我的代码和 6 楼代码一样,不过 6 楼代码貌似没有 i,没有爱,是不是不对啊?
没有 ---爱!---,,,,,是不行滴~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/646951

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX