【问题标题】:Nested for loop comparing files嵌套for循环比较文件
【发布时间】:2012-07-03 11:47:28
【问题描述】:

我正在尝试编写一个 bash 脚本来查看两个同名的文件,每个文件位于不同的目录中。

我知道这可以用 diff -r 完成,但是,我想将第二个文件中不在第一个文件中的所有内容输出到一个新文件中(也具有相同的文件名)

我用 grep 命令编写了一个(嵌套的)循环,但它不好并且返回了一个语法错误:

#!/bin/bash
FILES=/Path/dir1/*
FILES2=/Path/dir2/*

for f in $FILES
do
for i in $FILES2
do 
if $f = $i
grep -vf $i $f > /Path/dir3/$i

done
done

非常感谢任何帮助。

【问题讨论】:

    标签: bash loops grep


    【解决方案1】:

    试试这个

    #!/bin/bash
    cd /Path/dir1/
    for f in *; do
        comm -13 <(sort $f) <(sort /Path/dir2/$f) > /Path/dir3/$f
    done
    

    如果shell中的语法是

    if test_command;then commands;fi
    

    如果 test_command 退出代码为 0,则执行命令

    if [ $f = $i ] ; then  grep ... ; fi
    

    但在您的情况下,获取文件名会更有效

    for i in $FILES; do
        f=/Path/dir2/`basename $i`
        grep
    done
    

    最后,也许这会比 grep -v 更有效

    comm -13 <(sort $f) <(sort $i)
    

    comm -13 将获得第二个而不是第一个的所有内容;不带参数的 comm 生成 3 列输出:第一列仅在第一列中,第二列仅在第二列中,第三列中常见。 -13 或 -1 -3 删除第一列和第三列

    【讨论】:

    • 可爱,这很有效,我坚持使用它,但感谢大家,我感谢所有的答案。
    【解决方案2】:
    #!/bin/bash
    DIR1=/Path/dir1
    DIR2=/Path/dir2
    DIR3=/Path/dir3
    
    for f in $DIR1/*
    do
      for i in $DIR2/*
      do 
        if [ "$(basename $f)" = "$(basename $i)" ]
        then
          grep -vf "$i" "$f" > "$DIR3/$(basename $i)"
        fi
      done
    done
    

    【讨论】:

    • 谢谢,已经尝试过了,因为它最接近我的原作,因此对我来说更容易理解;)它不能以它的基本形式工作,然后我意识到基线名称是关键,所以我已将其更改为:code #!/bin/bash codeDIR1=/Path1/ codeDIR2=/Path2/ codeDIR3=/Path3/ code for f in $DIR1/* @987654327 @ do code for i in $DIR2/* code do code if [ "$DIR1/$(basename $f)" = "$DIR2/$(basename $i)" ] then grep -vf " $i" "$f" > "$DIR3/$(basename $i)" fi code done codedone 但是我仍然没有输出,不知道我在做什么。
    • 哦,我才意识到它是什么。在循环中,$f 最终成为 /Path/dir1/&lt;file&gt;$i 最终成为 /Path/dir2/&lt;file&gt;,所以当然两者不相等。我修好了,再试一次。
    • 是的,这就是我想说的。您的编辑效果很好。我使用@Nahuel Fouilleul 的解决方案只是因为输出已经为我排序了!
    【解决方案3】:

    这假定文件名中没有特殊字符。 (例如,空格。如果不可接受,请使用双引号。):

    a=/path/dir1
    b=/path/dir2
    for i in $a/*; do test -e $b/${i##*/} && 
       diff $i $b/${i##*/} | sed -n '/^< /s///p'; done 
    

    【讨论】:

    • 谢谢。我没有得到任何输出,这很奇怪。当我开始手动执行此操作时,文件中肯定有不同(和相似)的行。我不确定我做错了什么。
    • @jksl 小修改:使用## 而不是# 修剪前导路径。
    猜你喜欢
    • 1970-01-01
    • 2016-06-01
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 2018-05-14
    • 2018-11-11
    相关资源
    最近更新 更多