删除除 1 之外的所有重复图像文件

删除除 1 之外的所有重复图像文件

我有一个图像文件夹,其中包含相当多的重复项,我想删除除一个之外的所有重复项。

通过谷歌搜索,我发现了这个聪明的脚本这个帖子简洁地说几乎我想要它做什么:

#!/bin/sh -eu
find "${1:-.}" -type f ! -empty -print0 | xargs -0 md5 -r | \
    awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}' | \
    xargs -0 rm -v --

不幸的是,我对 UNIX shell 脚本还很陌生,所以我不确定每个部分的实际命令/标志在这里做什么,所以我无法根据我的特定需求对其进行修改。

据我了解:

find "${1:-.}" -type f ! -empty -print0- 搜索当前目录中的非空文件并打印文件名。 (虽然不确定这首曲子的"${1:-.}"意思)

| xargs -0 md5 -r- 将上面的结果(通过xargs -0命令?)传送到md5命令中以获取每个文件的 md5 哈希签名(-r反转输出以使其成为单行?)

awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}'- 这就是我迷路的地方..

  • $1 in a{sub("^.{33}","")- 获取输入直到第一个空白字符,并将字符串开头的前 33 个字符替换为空 ( sub("^.{33}","")
  • printf "%s\0"- 格式打印整个字符串
  • a{...,$0}- 我不知道这是做什么的
  • a[$1]+=1{}- 也不确定

xargs -0 rm -v --- 将结果通过管道传输到rm命令,通过 打印每个文件名-v,但我不确定语法--的用途。

当我运行它时,它输出如下,./test3.jpg./test2.jpg./test.jpg: No such file or directory所以一定存在格式问题。

我的问题是:

  1. 可以修改它以删除除 1 之外的所有文件吗?
  2. 有人可以帮助解释我上面概述的命令/语法含义之间的差距吗?

我相信这对于熟悉 UNIX 的人来说可能很容易,但不幸的是那个人不是我。提前谢谢您!

对于上下文:我在 macOS BigSur 11 的 ZSH 中运行它。

答案1

我将重点关注awk这里的 - 部分:

md5 -r返回 32 个字符的 md5-sum,然后返回文件名。因此 md5-sum 是 中的第一个字段awk

$1 in a{...}

意思是“如果$1(这里:md5-sum)被发现作为数组中的索引,a则执行命令{...}”。因此a将被用作一个数组,其中 md5 和作为已经看到的索引。请注意,如果该值不存在或为 0,则不会执行该命令 - 因此第一次看到 md5-sum 时,文件名是不是回。如果它是任何其他值(包括字符串),则条件为 true,并且执行命令。

sub("^.{33}","");printf "%s\0",$0

将从开头删除 33 个字符,即 md5-sum 和后面的空格,然后打印其余部分(原始文件名),末尾带有 NUL 分隔符。 NUL 分隔对于带有空格等的文件很重要。参见-print0man find-0man xargs。请注意,仅当 md5-sum 已在 array 中时才运行此命令a,因此不会返回第一个匹配项(即仅显示重复项,稍后将其删除)。

a[$1]+=1{}

“数组的元素$1加1 a”,$1是md5-sum。因此,a一旦看到 md5-sum,就会设置该值。这是重复计数器。 '{}' 是空命令。这是必要的,因为awk默认情况下,如果满足条件且未给出命令,则返回完整记录。


警告

据我所知,该脚本对于带有空格的文件工作正常,但我认为对于名称中带有换行符的文件来说它会失败,因为awk没有将 NUL 设置为记录分隔符,然后将默认为换行符。BEGIN {RS="\x0"}首先使用inawk进行设置。

相关内容