使用BASH将CVS diff中的结果排序到一个文件中

使用BASH将CVS diff中的结果排序到一个文件中,bash,cvs,Bash,Cvs,我正在尝试更改bash脚本,以便它将所有更改放在每个文件下,而不是重复相同的文件名 因此,我使用以下命令执行一个diff: grep Index ${logs}/${file_diff} | cvs -q diff -r $pTag $pathDir | sed -r 's/^.+\///' > ${logs}/${output_filename} 以上内容将显示输出文件名中上一个标记的更改结果。但问题在于pathDir pathDir在相同的文件中有更改,但每个主题的路径不同: 因此p

我正在尝试更改bash脚本,以便它将所有更改放在每个文件下,而不是重复相同的文件名

因此,我使用以下命令执行一个diff:

grep Index ${logs}/${file_diff} | cvs -q diff -r $pTag $pathDir | sed -r 's/^.+\///' > ${logs}/${output_filename}
以上内容将显示
输出文件名中上一个标记的更改结果。但问题在于
pathDir

pathDir
在相同的文件中有更改,但每个主题的路径不同:

因此
pathDir
包含指向

this/is/the/path/to/the/changes/for/apples

this/is/the/path/to/the/changes/for/bananas

this/is/the/path/to/the/changes/for/grapes
但在这些路径中,文件名change.dat包含所有更改

我是否可以更改grep以显示just change.dat下苹果、香蕉和葡萄的所有更改

目前,它显示的变化如下:

this/is/the/path/to/the/changes/for/apples/change.dat

{Apple changes here}

this/is/the/path/to/the/changes/for/bananas/change.dat

{Banana changes here}

this/is/the/path/to/the/changes/for/grapes/change.dat

{Grape changes here}
由于更改在change.dat中,我想合并它们,以便只显示
change.dat
中的更改

谢谢

#!/bin/bash
# the above shebang line MUST be #!/bin/bash, since we use features not in /bin/sh

exec 3>/dev/null                        # start out with FD 3 writing to /dev/null
while read -r; do                       # iterate over lines in the cvs diff
  if [[ $REPLY = "Index: "* ]]; then    # when we see a line starting with "Index: "...
    full_filename=${REPLY%"Index: "}    # ...extract the filename
    base_filename=${full_filename##*/}  # ...then extract only the basename
    exec 3>>"$base_filename"            # ...then open FD 3 to append to the basename
    printf '%s\n' "$REPLY" >&3          # ...then write the index line itself
  else                                  # for lines that don't start with "Index: "...
    printf '%s\n' "$REPLY" >&3          # ...write the line to the existing FD3
  fi
done < <(cvs -q diff -r "$pTag" "$pathDir") # do the above for the output from cvs diff
有关逐行读取输入的方法的更多信息,请参阅

有关上面使用的字符串操作技术的更多信息,或者有关bash中字符串操作的更温和的介绍,请参见


有关如何使用
exec
的更多信息,请参见此处(页面的其他部分也可能是很好的阅读资料)。

有关样式的一些基本说明--
${foo}
作为独立参数使用时,不会超过
$foo
。对扩展安全性有很大影响的是引用--
“$foo”总是会扩展成一个参数,而
$foo
${foo}
可以是零、一或多个……另外,您最初的
grep
实际上做了什么吗?因为它从左边的内容读取输入(管道从左到右),所以它永远看不到右边
cvs diff
的输出,也不能以任何方式与之交互(因为
cvs diff
据我所知,它不从stdin读取…这是这两个进程之间的唯一连接)谢谢你的帮助,我真的很感激。我使用的grep显示的是diff的结果,而不是管道中使用的diff。它实际上使用的是在这个文件${file_diff}中创建的diff。谢谢你指出这一点。我正在阅读下面的答案,并在我的脚本中进行测试。Thankstorry我在定位生成${logs}/${output_filename}的位置时遇到问题。输出。@Raj,在第一种情况下,您希望将其设置为“$logs/$base\u filename””。在第二个示例中,所有输出都合并到stdout.sorry,但根本没有从中创建文件。我在顶部替换了这个:exec 3>>“$$logs/$base\u filename”。不确定它为什么不生成文件。@Raj,不要更改顶部的文件,更改循环中的文件。在顶部,您还不知道正在处理的文件是什么,因此基本文件名是未设置的。我认为您版本中的
$$
是一个打字错误,不是您试图完成的任务的合法表示。除此之外,
set-x
是您调试的朋友。我猜您的代码从未看到
索引
行(这意味着
[[$REPLY=“Index:*]]
测试从未匹配);检查
set-x
输出将解释为什么会这样。
#!/bin/bash
# the above shebang line MUST be #!/bin/bash, since we use features not in /bin/sh

while read -r; do                       # iterate over lines in the cvs diff
  if [[ $REPLY = "Index: "* ]]; then    # when we see a line starting with "Index: "...
    full_filename=${REPLY%"Index: "}    # ...extract the filename
    base_filename=${full_filename##*/}  # ...then extract only the basename
  fi
  # print to stdout if and only if the current filename is change.dat
  [[ $base_filename = change.dat ]] && printf '%s\n' "$REPLY"
done < <(cvs -q diff -r "$pTag" "$pathDir") # do the above for the output from cvs diff