【问题标题】:Do md5sum on files inside a directory and check if there are identical files对目录中的文件执行 md5sum 并检查是否有相同的文件
【发布时间】:2017-03-29 16:02:04
【问题描述】:

我正在研究 shell 脚本,有一个练习要求计算文件夹中所有文件的 md5 哈希值。如果有两个文件具有相同的哈希值,它还要求在终端中打印它们的名称。我的代码可以做到这一点,但是一旦找到匹配项,就会打印两次。我不知道如何从下一次迭代中排除第一个文件名。 另一件事:禁止创建任何临时文件来帮助完成任务。

#!/bin/bash

ifs=$IFS
IFS=$'\n'

echo "Verifying the files inside the directory..."

for file1 in $(find . -maxdepth 1 -type f | cut -d "/" -f2); do
  md51=$(md5sum $file1  | cut -d " " -f1)
  for file2 in $(find . -maxdepth 1 -type f | cut -d "/" -f2 | grep -v "$file1"); do
    md52=$(md5sum $file2 | cut -d " " -f1)
    if [ "$md51" == "$md52" ]; then
      echo "Files $file1 e $file2 are the same."
    fi
  done
done

我也想知道是否有更有效的方法来完成这项任务。

【问题讨论】:

  • 当然有。如果您打印出每个文件 md5sum,对它们进行排序并找到两个或多个连续的 md5sum 会怎样? find ··· | xargs md5sum | sort | uniq ···

标签: bash shell md5 md5sum


【解决方案1】:

这个

mapfile -t list < <(find . -maxdepth 1 -type f -exec md5sum {} + | sort)
mapfile -t dups < <(printf "%s\n" "${list[@]}" | grep -f <(printf "^%s\n" "${list[@]}" | sed 's/ .*//' | sort | uniq -d))

# here the array dups containing the all duplicates along with their md5sum
# you can print the array using a simple
printf "%s\n" "${dups[@]}"

会得到如下输出:

3b0332e02daabf31651a5a0d81ba830a  ./f2.txt
3b0332e02daabf31651a5a0d81ba830a  ./fff
c9eb23b681c34412f6e6f3168e3990a4  ./both.txt
c9eb23b681c34412f6e6f3168e3990a4  ./f_out
d41d8cd98f00b204e9800998ecf8427e  ./aa
d41d8cd98f00b204e9800998ecf8427e  ./abc def.xxx
d41d8cd98f00b204e9800998ecf8427e  ./dudu
d41d8cd98f00b204e9800998ecf8427e  ./start
d41d8cd98f00b204e9800998ecf8427e  ./xx_yy

以下添加只是为了更精美的打印输出

echo "duplicates:"
while read md5; do
        echo "$md5"
        printf "%s\n" "${dups[@]}" | grep "$md5" | sed 's/[^ ]* /  /'
done < <(printf "%s\n" "${dups[@]}" | sed 's/ .*//' | sort -u)

将打印如下内容:

3b0332e02daabf31651a5a0d81ba830a
   ./f2.txt
   ./fff
c9eb23b681c34412f6e6f3168e3990a4
   ./both.txt
   ./f_out
d41d8cd98f00b204e9800998ecf8427e
   ./aa
   ./abc def.xxx
   ./dudu
   ./start
   ./xx_yy

警告:仅当文件名不包含\n(换行符)字符时才有效。修改脚本一般需要bash4.4+,其中mapfile知道-d参数。

【讨论】:

  • 禁止创建任何临时文件来帮助完成任务。
  • @cmks 你知道readarray 只是mapfile 的另一个名字吗?尝试:help readarrayhelp mapfile... 解决方案中没有使用临时文件 - 也许您需要更仔细地阅读。 ;)
  • @jm666 它就像一个魅力,这个更精美的打印输出太棒了!感谢您的帮助!
  • 你能推荐我一本关于shell脚本的书吗?我不是新手,但我不知道的大部分台词都可以按照你的方式完成。
【解决方案2】:

这是一种更有效的方法,它不使用任何临时文件:

#!/bin/bash

# get the sorted md5sum list of all files into an array in one shot
readarray -t arr < <(find . -maxdepth 1 -type f -exec md5sum {} + | sort)
# loop through the array and compare md5sum of contiguous items
for i in "${arr[@]}"; do
  md5="${i/ */}" # extract md5sum part
  [[ "$md5" = "$prev_md5" ]] && printf '%s\n' "$prev_i" "$i"
  prev_md5="$md5"
  prev_i="$i"
done | sort -u
  • 需要sort -u 才能删除两个以上相同文件时打印的重复项

【讨论】:

  • 你能推荐我一本关于shell脚本的书吗?我不是新手,但我不知道的大部分台词都可以按照你的方式完成。
  • @UlissesAlves - 我最近的 Bash 知识大部分来自 StackOverflow。主要是通过观察像 Charles Duffy、chepner、anubhava、barmar、Jonathan Leffler 等专家如何回答问题。我也看看他们的旧答案。另一个很棒的地方是Info tab on the Bash tag page
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多