通过 unix 命令行从文件组中批量删除较小的文件

通过 unix 命令行从文件组中批量删除较小的文件

我有大量(超过 400 个)目录,里面都是照片。我想要做的是保留这些照片的较大尺寸。每个目录中有 31 到 66 个文件。

每个目录都有缩略图和更大的版本,以及一个名为example.jpg

我使用以下命令轻松发送了 example.jpg 文件:

rm */example.jpg

我最初以为删除缩略图很容易,但问题是它们的名称不一致。典型的模式是photo1.jpgphoto1s.jpg。我这样做了rm */photo*s.jpg,但结果发现一些文件的名称photoXs.jpg实际上更大而不是更小。啊。

因此,我想要做的是扫描每个目录的文件大小并删除(或移动)缩略图。我最初以为我只是扫描ls -R每个文件并提取每个文件的大小,然后将它们保存在阈值以下。问题是什么?在一个目录中,大文件为 1.1 MB,缩略图为 200k。在另一个目录中,大文件为 200k,小文件为 30k。

更糟糕的是,这些文件实际上大多都有名称photo1.jpg- 因此,如果不重命名,简单地将它们全部放在同一个文件夹中、按大小排序并分组删除是行不通的,如果可能的话,我宁愿将它们保留在各自的文件夹中。

我几乎决定只手动完成所有操作,但后来想在这里问一下。

您将如何完成这项任务?

答案1

此脚本假设最小文件组和最大文件组之间的大小存在明显差距。具体来说,大文件中最小的文件至少是小文件中最大文件的两倍。

调用脚本“imagedirstats”并循环运行,如下所示:

find /path/to/main/branch -type d | while read subdir; do (cd "$subdir" && ~/bin/imagedirstats ); done

为了查找和删除目录树中各个目录中的文件。

脚本如下:

#!/bin/bash
# from http://superuser.com/questions/135951/batch-deletion-of-smaller-files-from-group-of-files-via-unix-command-line
# by Dennis Williamson - 2010-04-29

prevn=1     # prevent division by zero
factor=4    # how close to the largest of the small files to set the threshold, 4 == one fourth of the way above
min=1000    # ignore files below this size

while read n
do
    (( ratio = n / prevn ))
    if (( ratio > 1 && n > min ))
    then
        break
    fi
    if (( n > 0 ))
    then
        prevn=$n
    fi
done < <(find . -maxdepth 1 -name "*.jpg" -printf "%s\n" | sort -n)
# for OS X, comment out the preceding line and uncomment this one:
# done < <(find . -maxdepth 1 -name "*.jpg" | stat -f "%z" | sort -n)

# the following line would be the GNU equivalent using stat(1) instead of printf
# it's included here for reference:
# done < <(find . -maxdepth 1 -name "*.jpg" | stat -c "%s" | sort -n)

(( size = (n - prevn) / factor + prevn ))

echo "Smallest of the large: $n"
echo "Largest of the small: $prevn"
echo "Ratio: $ratio"
echo "Threshold: $size"

if (( ratio < 2 ))
then
    read -p "Warning: ratio too small. Delete anyway? Only 'Yes' will proceed" reply
    if [[ $reply != "Yes" ]]
    then
        echo "Cancelled" >&2
        exit 1
    fi
fi

# uncomment the delete on the following line to actually do the deletion

find . -maxdepth 1 -name "*.jpg" -size -${size}c # -delete

编辑:移动了警告提示,以便首先显示有用的信息。修复了缺失的fi

编辑2:使两个find命令一致。为 OS X 添加了注释掉的变体。添加了有关运行脚本的信息。

答案2

如果您发现有一些特定的截止值,例如所有大图片都大于 200KB,那么您可以执行以下操作:

find */*.jpg -size -200k -delete

您可能需要先制作一个备份。

答案3

如果文件大小不一致,图像尺寸是否一致?

您可以使用identifyImageMagick 附带的工具来获取图像尺寸。通过一些简单的 bash 脚本,您可以根据图像的大小对其进行处理。

要获取图像的宽度和高度,请使用identify

识别 -格式'%wx%h'文件名

您将获得如下输出:

[john@awesome:~]$ 识别 -格式'%wx%h' W4.JPG
1680x1050

然后您可以使用该cut实用程序来获取脚本中的数字:

[john@awesome:~]$ 识别 -格式'%wx%h'W4.JPG | 剪切-d'x'-f1
1680
[john@awesome:~]$ 识别 -格式'%wx%h' W4.JPG | 剪切 -d'x' -f2
1050

答案4

如果您想根据文件名执行此操作,请尝试以下操作:

find -name '*.jpg' | sed -ne 's:^\(.*\)\.jpg:\1s.jpg$:p' | xargs rm

它将找到每个 .jpg 文件,在文件名末尾(“.”之前)添加一个“s”并将其删除。

相关内容