您的脚本中有很多问题。
首先,为了将命令的结果分配给变量,您需要将其用反斜线(`command`
)或最好用括起来$(command)
。您使用单引号('command'
)将其括起来,而不是将命令的结果分配给变量,而是将命令本身分配为字符串。因此,您test
实际上是:
$ echo "test $sum1=$sum2"
test find $i -type f -iname "*.jpg" -exec md5sum {} \;=find $j -type f -iname "*.jpg" -exec md5sum {} \;
下一个问题是该命令md5sum
返回的不仅是哈希值:
$ md5sum /etc/fstab
46f065563c9e88143fa6fb4d3e42a252 /etc/fstab
您只想比较第一个字段,因此您应该md5sum
通过仅输出第一个字段的命令来解析输出:
find $i -type f -iname "*.png" -exec md5sum '{}' \; | cut -f 1 -d ' '
要么
find $i -type f -iname "*.png" -exec md5sum '{}' \; | awk '{print $1}'
同样,该find
命令将返回许多匹配项,而不仅仅是一个匹配项,并且每个匹配项都将被第二个重复find
。这意味着您将在某个时候将同一个文件与其自身进行比较,md5sum将是相同的,最终您将删除所有文件(我在包含a.jpg
和的测试目录上运行了该文件b.jpg
):
for i in $(find . -iname "*.jpg"); do
for j in $(find . -iname "*.jpg"); do
echo "i is: $i and j is: $j"
done
done
i is: ./a.jpg and j is: ./a.jpg ## BAD, will delete a.jpg
i is: ./a.jpg and j is: ./b.jpg
i is: ./b.jpg and j is: ./a.jpg
i is: ./b.jpg and j is: ./b.jpg ## BAD will delete b.jpg
for i in directory_path
除非要传递目录数组,否则您不希望运行。如果所有这些文件都在同一目录中,则要运行for i in $(find directory_path -iname "*.jpg"
)以遍历所有文件。
在find的输出中使用循环是一个坏主意for
。您应该使用while
循环或遍历:
find . -iname "*.jpg" | while read i; do [...] ; done
或者,如果所有文件都位于同一目录中:
for i in *jpg; do [...]; done
根据您的shell和设置的选项,即使对于子目录中的文件,也可以使用globing,但在此不做介绍。
最后,还应该引用变量,否则带空格的目录路径将破坏脚本。
文件名可以包含空格,换行,反斜杠和其他奇怪的字符,要在while
循环中正确处理这些文件,您需要添加更多选项。您要编写的内容如下:
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' i; do
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' j; do
if [ "$i" != "$j" ]
then
sum1=$(md5sum "$i" | cut -f 1 -d ' ' )
sum2=$(md5sum "$j" | cut -f 1 -d ' ' )
[ "$sum1" = "$sum2" ] && rm "$j"
fi
done
done
一个更简单的方法是:
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm $F[1]") if $k{$F[0]}>1'
更好的版本可以处理文件名中的空格:
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm \"@F[1 .. $#F]\"") if $k{$F[0]}>1'
这个小的Perl脚本将贯穿find
命令的结果(即md5sum和文件名)运行。在-a
供选择perl
的空白拆分输入线并保存它们中F
的数组,所以$F[0]
将md5sum也和$F[1]
文件名。md5sum保存在哈希中k
,脚本检查哈希是否已经被看到(if $k{$F[0]}>1
),并在文件已删除()的情况下删除该文件system("rm $F[1]")
。
虽然可以正常工作,但是对于大型图像集合来说将非常慢,并且您无法选择保留哪些文件。有许多程序可以更优雅地处理此问题,包括: