我有一个包含几千个文件的目录,名称如下:
filename.ext
filename (1).ext
filename (2).ext
otherfile.ext
otherfile (1).ext
etc.
大多数带有括号的数据都是原始文件的副本,但在某些情况下它们不是。
如何保留原始文件,删除重复文件,但不丢失不同的文件?
我知道我可以rm *\).ext
,但这显然无法确保文件与原始文件相符。
我正在使用OS X,所以我有一个md5
程序,其功能类似于Linux中的md5sum
,尽管它将哈希值放在行的末尾而不是开头。我以为我可以使用awk脚本获取md5 *.ext | awk 'some script'
的输出,通过md5查找重复项,然后删除它们,但命令行太长(bash: /sbin/md5: Argument list too long
)。
我不知道在脚本中要写什么。我想用这个来存储数组:
awk '{a[$NF]++} a[$NF]>1{sub(/).*/,""); sub(/.*(/,""); system("rm " $0);}'
但这似乎总是删除我原来的。
我做错了什么?我该怎么做?
感谢。
答案 0 :(得分:6)
您的awk脚本会删除原始文件,因为在对文件进行排序时,.
(句点)会在(空格)之后排序。所看到的第一个文件是编号的,而不是原始文件,后续检查(包括原始文件)与第一个编号的文件进行比较。
rm *\).txt
不仅与原作不匹配,而且首先会丢失可能没有原始文件的文件。
我不会这样做。您可以浏览原始列表,然后删除与其匹配的编号文件,而不是检查每个编号文件并验证它是否与原始文件匹配。
相反:
$ for file in *[^\)].txt; do echo "-- Found: $file"; rm -v $(basename "$file" .txt)\ \(*\).txt; done
您可以展开此选项以检查MD5。但它的代码更多,所以我会在脚本中将它分成多行:
#!/bin/bash
shopt -s nullglob # Show nothing if a fileglob matches no files
for file in *[^\)].ext; do
md5=$(md5 -q "$file") # The -q option gives you only the message digest
echo "-- Found: $file ($md5)"
for duplicate in $(basename "$file" .ext)\ \(*\).ext; do
if [[ "$md5" = "$(md5 -q "$duplicate")" ]]; then
rm -v "$duplicate"
fi
done
done
作为替代方案,您可以更轻松地完成此操作,与计算MD5摘要相比,CPU开销更少。 Unix和Linux有一个名为cmp
的shell工具,它与没有输出的diff
类似。所以:
#!/bin/bash
shopt -s nullglob
for file in *[^\)].ext; do
for duplicate in $(basename "$file" .ext)\ \(*\).ext; do
if cmp "$file" "$duplicate"; then
rm -v "$file"
fi
done
done
答案 1 :(得分:0)
如果你不需要使用AWK,你可以在bash中做一些更简单的事情:
for file in *\([0-9]*\)*; do
[ -e "$(echo "$file" | sed -e 's/ ([0-9]\+)//')" ] && rm "$file"
done
希望这有点帮助=)