BASH while循环检查文件中的行显示次数太多

时间:2013-06-13 19:59:03

标签: bash loops while-loop echo

我正在编写一个脚本,我想从文件中获取每一行并检查另一个文件中的匹配项。 如果我找到一场比赛,我想说我找到了一场比赛,如果没有,请说我找不到比赛。

这2个文件包含md5哈希值。旧文件是原始文件,新文件用于检查自原始文件以来是否有任何更改。

原始文件:chksum 新文件:chksum1

#!/bin/bash

while read e; do
     while read f; do
     if [[ $e = $f ]]
     then 
     echo $e "is the same"
     else
          if [[ $e != $f]]
          then
          echo $e "has been changed"
          fi
     fi
     done < chksum1
done < chksum

我的问题是,对于已经更改的文件,每次完成循环中的检查时我都会得到一个回声,而我只希望它显示一次文件,并说它没有找到。

希望这很清楚。

6 个答案:

答案 0 :(得分:0)

你可以使用相同的脚本但提醒一下。

#!/bin/bash

while read e; do
    rem=0
        while read f; do
        if [[ $e = $f ]]
        then 
            rem=1
        fi
        done < chksum1
    if [[ rem = 1 ]] 
    then
        echo $e "is the same"
    else
        echo $e "has been changed"
    fi
done < chksum

这应该可以正常工作

答案 1 :(得分:0)

你真的很亲密。这将有效:

while read e; do
     while read f; do
     found=0
     if [[ $e = $f ]]
     then 
         # echo $e "is the same"
         found=1
         break
     fi
     done < chksum1
     if [ $found -ne 0 ]
     then
        echo "$e is the the same"
     else
        echo "$e has been changed"
     fi
done < chksum

答案 2 :(得分:0)

一点点简化版本,避免多次读取同一文件( 4.0及以上版本)。我假设文件包含唯一的文件名,文件格式是命令的输出。

#!/bin/bash

declare -A hash
while read md5 file; do hash[$file]=$md5; done <chksum
while read md5 file; do
  [ -z "${hash[$file]}" ] && echo "$file new file" && continue
  [ ${hash[$file]} == $md5 ] && echo "$file is same" && continue
  echo "$file has been changed"
done <chksum1

此脚本将第一个文件读取到一个名为hash的关联数组。索引是文件的名称,值是MD5校验和。第二个循环读取第二个校验和文件;文件名不在hash打印file new file;如果它在hash并且值等于那么它是同一个文件;如果它不等于它写file has been changed

输入文件:

$ cat chksum
eed0fc0313f790cec0695914f1847bca  ./a.txt
9ee9e1fffbb3c16357bf80c6f7a27574  ./b.txt
a91a408e113adce865cba3c580add827  ./c.txt
$ cat chksum1
eed0fc0313f790cec0695914f1847bca  ./a.txt
8ee9e1fffbb3c16357bf80c6f7a27574  ./b.txt
a91a408e113adce865cba3c580add827  ./d.txt

输出:

./a.txt is same
./b.txt has been changed
./d.txt new file

扩展版

还检测已删除的文件。

#!/bin/bash

declare -A hash
while read md5 file; do hash[$file]=$md5; done <chksum
while read md5 file; do
  [ -z "${hash[$file]}" ] && echo "$file new file" && continue
  if [ ${hash[$file]} == $md5 ]; then echo "$file is same"
  else echo "$file has been changed"
  fi
  unset hash[$file]
done <chksum1
for file in ${!hash[*]};{ echo "$file deleted file";}

输出:

./a.txt is same
./b.txt has been changed
./d.txt new file
./c.txt deleted file

答案 3 :(得分:0)

我想建议一个替代解决方案:如何逐行阅读,但使用sortuniq -c查看是否存在差异。没有必要使用简单的管道来完成工作。

在这种情况下,您需要文件chksum1中已更改的所有行,所以

sort chksum chksum1 chksum1 | uniq -c | egrep '^\s+2\s' | sed 's%\s\+2\s%%'

与基于循环的示例相比,这也只读取chksum1 2次,每个行chksum读取一次。

重用其他答案之一的输入文件:

samveen@precise:~/so$ cat chksum
eed0fc0313f790cec0695914f1847bca  ./a.txt
9ee9e1fffbb3c16357bf80c6f7a27574  ./b.txt
a91a408e113adce865cba3c580add827  ./c.txt

samveen@precise:~/so$ cat chksum1
eed0fc0313f790cec0695914f1847bca  ./a.txt
8ee9e1fffbb3c16357bf80c6f7a27574  ./b.txt
a91a408e113adce865cba3c580add827  ./d.txt

samveen@precise:~/so$ sort chksum chksum1 chksum1 |uniq -c | egrep '^\s+2\s' |sed 's%\s\+2\s%%'
8ee9e1fffbb3c16357bf80c6f7a27574  ./b.txt
a91a408e113adce865cba3c580add827  ./d.txt

另一种可能的解决方案是(在问题的评论中建议)将diffsort结合使用:

diff <(sort chksum) <(sort chksum1) |grep '^>'

输出:

samveen@precise:~/so$ diff <(sort chksum) <(sort chksum1) |grep '^>'
> 8ee9e1fffbb3c16357bf80c6f7a27574  ./b.txt
> a91a408e113adce865cba3c580add827  ./d.txt

答案 4 :(得分:0)

简单的解决方案:

diff -q chksum1 chksum

答案 5 :(得分:0)

使用命令grep怎么样?您从chksum读取的每一行都将作为chksum1中的搜索模式。如果grep找到匹配项,则包含grep返回值的"$?"将等于0,否则它将等于1

while read e; do  
  grep $e checksum1
  if[ $? == "0" ];then
     echo $e "is the same"
  else
     echo $e "has been changed"
  fi
done < chksum