2012-09-13 40 views
4

我明显错过了一些简单的东西,并且知道问题在于它创建了一个空白输出,这就是为什么它无法比较。但是,如果有人能够对此有所了解,那就太好了 - 我没有把它隔离开来。Bash循环来比较文件

最终,我试图将md5sum从存储在txt文件中的列表与存储在服务器上的列表进行比较。如果有错误,我需要它来报告。以下是输出:

[email protected] [~/testinggrounds]# cat md5.txt | while read a b; do 
> md5sum "$b" | read c d 
> if [ "$a" != "$c" ] ; then 
>  echo "md5 of file $b does not match" 
> fi 
> done 
md5 of file file1 does not match 
md5 of file file2 does not match 

[email protected] [~/testinggrounds]# md5sum file* 
2a53da1a6fbfc0bafdd96b0a2ea29515 file1 
bcb35cddc47f3df844ff26e9e2167c96 file2 

[email protected] [~/testinggrounds]# cat md5.txt 
2a53da1a6fbfc0bafdd96b0a2ea29515 file1 
bcb35cddc47f3df844ff26e9e2167c96 file2 

回答

3

我不会去争辩。我只是试图避免内部循环的双重读取。

#! /bin/bash 

cat md5.txt | while read sum file 
do 
    prev_sum=$(md5sum $file | awk '{print $1}') 
    if [ "$sum" != "$prev_sum" ] 
    then 
     echo "md5 of file $file does not match" 
    else 
     echo "$file is fine" 
    fi 
done 
4

您遇到的问题是您的内部读取是在子外壳中执行的。在bash中,管道命令时会创建一个子shell。一旦子外壳退出,变量$ c和$ d就消失了。您可以使用进程替换,以避免子shell:

while read -r -u3 sum filename; do 
    read -r cursum _ < <(md5sum "$filename") 
    if [[ $sum != $cursum ]]; then 
     printf 'md5 of file %s does not match\n' "$filename" 
    fi 
done 3<md5.txt 

重定向3<md5.txt导致被打开的文件描述符3. -u 3选项read导致它从该文件进行读取的文件。内部read仍然从stdin读取。

+0

内部'read'命令不是从封闭while循环继承stdin;它通过管道连接到'md5sum'。您正在通过在内部读取中使用流程替换(而不是管道)来解决问题,而不是通过为外部循环使用单独的文件描述符。 – chepner

+0

@chepner - 你是对的,我更新了答案。 – jordanm

7

不能直接回答你的问题,但md5sum(1)

-c, --check 
read MD5 sums from the FILEs and check them 

像:

$ ls 
1.txt 2.txt md5.txt 
$ cat md5.txt 
d3b07384d113edec49eaa6238ad5ff00 1.txt 
c157a79031e1c40f85931829bc5fc552 2.txt 
$ md5sum -c md5.txt 
1.txt: OK 
2.txt: OK 
+0

这可能是最好的路线,但我打赌不是所有版本的md5sum都支持这一点。但问题是标签为linux。 – jordanm

+0

+1非常流畅。 –