在shell中,如何删除编号的重复文件?

Gra*_*ham 6 bash awk

我有一个包含几千个文件的目录,命名为:

filename.ext
filename (1).ext
filename (2).ext
otherfile.ext
otherfile (1).ext
etc.
Run Code Online (Sandbox Code Playgroud)

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

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

我知道我可以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);}'
Run Code Online (Sandbox Code Playgroud)

但这似乎总是删除我原来的.

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

谢谢.

gho*_*oti 6

您的awk脚本会删除原始文件,因为在对文件进行排序时,.(句点)会在 (space). SO the first file that's seen is numbered, not the original, and subsequent checks (including the one against the original) compare files to the first numbered one.

Not only does rm *\).txt符合原始版本,它首先会丢失可能没有原件的文件.

我不会这样做.您可以浏览原始列表,然后删除与其匹配的编号文件,而不是检查每个编号文件并验证它是否与原始文件匹配.

代替:

$ for file in *[^\)].txt; do echo "-- Found: $file"; rm -v $(basename "$file" .txt)\ \(*\).txt; done
Run Code Online (Sandbox Code Playgroud)

您可以展开它以检查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
Run Code Online (Sandbox Code Playgroud)

作为替代方案,您可以更简单地完成此操作,与计算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
Run Code Online (Sandbox Code Playgroud)