V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
kiev84
V2EX  ›  问与答

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

  •  
  •   kiev84 · 2020-02-24 01:09:43 +08:00 · 2228 次点击
    这是一个创建于 1741 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原因是这样的: 本人是摄影爱好者,因为拍摄时要兼顾出图速度和质量,因此相机设置为同时拍 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.


    非常非常感谢!

    8 条回复    2020-02-24 16:15:17 +08:00
    CEBBCAT
        1
    CEBBCAT  
       2020-02-24 02:14:14 +08:00 via Android
    逻辑非常清晰,我想明天试试写一个,但害怕出了问题追悔莫及。楼主有做备份吗?

    Google Photos 提供近乎没有压缩的无限备份
    wtks1
        2
    wtks1  
       2020-02-24 02:23:57 +08:00 via Android
    不计较速度的话,写起来应该不麻烦,脚本先遍历一遍,把所有 raw 的文件名都储存在 sqlite 的表里,然后再遍历 jpg,每一个文件都拿到数据库里查询一下,存在就删除,不存在就保留
    zhzy
        3
    zhzy  
       2020-02-24 02:27:44 +08:00 via iPhone
    一个建议:不要直接删除,把不要的照片按原来的路径重命名( y-m-d-文件名)然后移动到一个单独的文件夹里,随便找个地方备份冷存就行了,然后过一段时间确认真的不要了再删掉
    xiofee
        4
    xiofee  
       2020-02-24 03:37:28 +08:00   ❤️ 2
    在当前目录下查找同名 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
        5
    mcfog  
       2020-02-24 03:39:44 +08:00 via Android
    列出 raw 文件: find -name *.raw . (我可能写错,自己 man find) 或 ls | grep . raw
    遍历: xargs,或者 find 自带
    raw 后缀名替换 jpg: sed
    假删除(测试): echo
    真删除: mv <filename> /tmp
    ETiV
        6
    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
        7
    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
        8
    ps1aniuge  
       2020-02-24 16:15:17 +08:00
    我的代码和 6 楼代码一样,不过 6 楼代码貌似没有 i,没有爱,是不是不对啊?
    没有 ---爱!---,,,,,是不行滴~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2807 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 07:29 · PVG 15:29 · LAX 23:29 · JFK 02:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.