6

我有一个目录,里面有几千个文件,命名如下:

filename.ext
filename (1).ext
filename (2).ext
otherfile.ext
otherfile (1).ext
etc.

大多数带有括号数字的文件都是原始文件的副本,但在某些情况下它们不是。

如何保留原始文件,删除重复文件,但不丢失不同的文件?

我知道我可以rm *\).ext,但这显然不能确保文件与原始文件匹配。

我使用的是 OS X,所以我有一个md5功能类似于md5sumLinux 的程序,尽管它将散列放在行尾而不是开头。我在想我可以使用 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);}'

但这似乎总是删除我的原件。

我究竟做错了什么?我该怎么做?

谢谢。

4

2 回答 2

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 都有一个叫做 的 shell 工具cmp,它就像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
于 2012-10-03T17:10:43.333 回答
0

如果您不需要使用 AWK,您可以在 bash 中做一些更简单的事情:

for file in *\([0-9]*\)*; do
    [ -e "$(echo "$file" | sed -e 's/ ([0-9]\+)//')" ] && rm "$file"
done

希望这会有所帮助=)

于 2012-10-03T17:10:05.940 回答