BASH while循环检查文件中的行显示次数过多
我正在编写一个脚本,希望从一个文件中提取每一行,并在另一个文件中检查匹配项。 如果我找到了匹配项,我想说我找到了匹配项,如果没有,就说我没有找到匹配项 这两个文件包含md5哈希。旧文件是原始文件,新文件是检查自原始文件以来是否有任何更改 原始文件:chksum 新文件:chksum1BASH while循环检查文件中的行显示次数过多,bash,loops,while-loop,echo,md5sum,Bash,Loops,While Loop,Echo,Md5sum,我正在编写一个脚本,希望从一个文件中提取每一行,并在另一个文件中检查匹配项。 如果我找到了匹配项,我想说我找到了匹配项,如果没有,就说我没有找到匹配项 这两个文件包含md5哈希。旧文件是原始文件,新文件是检查自原始文件以来是否有任何更改 原始文件:chksum 新文件:chksum1 #!/bin/bash while read e; do while read f; do if [[ $e = $f ]] then echo $e "is the s
#!/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
我的问题是,对于已更改的文件,每次在循环中进行检查时,我都会收到一个回音,我只希望它显示一次文件,并说找不到该文件
希望这是清楚的。您可以使用相同的脚本,但要放一个提醒
#!/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
这应该是正确的你真的很接近了。这将有助于:
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
一个稍微简化的版本,避免了对同一个文件4.0及以上版本的多次读取。我假设这些文件包含唯一的文件名,并且文件格式是命令的输出 输出:
./a.txt is same
./b.txt has been changed
./d.txt new file
./a.txt is same
./b.txt has been changed
./d.txt new file
./c.txt deleted 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";}
我想建议另一种解决方案:不要逐行阅读,而是使用sort和uniq-c来查看是否有差异。不需要一个简单管道就能完成工作的回路 在本例中,您需要文件chksum1中所有已更改的行,因此 与基于循环的示例(每行chksum读取一次)相比,它也只读取chksum1 2次 重复使用其他答案之一的输入文件:
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
另一种可能的解决方案是在问题的评论中建议将diff与sort结合使用:
输出:
samveen@precise:~/so$ diff <(sort chksum) <(sort chksum1) |grep '^>'
> 8ee9e1fffbb3c16357bf80c6f7a27574 ./b.txt
> a91a408e113adce865cba3c580add827 ./d.txt
简单解决方案:
diff -q chksum1 chksum
使用grep命令怎么样。从chksum读取的每一行都将作为chksum1中的搜索模式。如果grep找到匹配项,则$?其中包含grep的返回值将等于0,否则将等于1
你能从你的文件中发布一些样本吗?IMO awk可以做得更好。为什么你不想使用差异?diff-chksum-chksum1将完全满足您的需要。次要添加:在else部分,您不需要检查值是否不同,因为它们确实不同。只需重复这句话。+1!谢谢你的提问!我又学到了一些东西。我再次阅读ManBash,发现${var:+val}和${var+val}的行为不同@有人说你做对了。保持简单似乎不在这里。我发布了一个使用sort和uniq的解决方案,但是diff即使不是更好,也可以工作。我不知道为什么,因为你的脚本对我来说很有意义,但它告诉我所有文件都已更改。这有点超前,但我会运行它并研究它。我想如果我将md5更改为用户输入变量,它将适用于sha1、sha512,等等?@BrantNanton:补充了一些解释。您不需要更改输入变量,它只是一个名称。您需要创建具有正确校验和的文件。如果第一列是校验和,第二列是文件名,您不需要更改任何内容。@BrantNanton:我看到了您的脚本,如果第一列是校验和,第二列是文件名,这个答案应该可以用于任何校验和计算。非常感谢,我将测试它
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
diff <(sort chksum) <(sort chksum1) |grep '^>'
samveen@precise:~/so$ diff <(sort chksum) <(sort chksum1) |grep '^>'
> 8ee9e1fffbb3c16357bf80c6f7a27574 ./b.txt
> a91a408e113adce865cba3c580add827 ./d.txt
diff -q chksum1 chksum
while read e; do
grep $e checksum1
if[ $? == "0" ];then
echo $e "is the same"
else
echo $e "has been changed"
fi
done < chksum