令人费解的csh重定向行为

时间:2014-12-04 11:26:25

标签: unix csh

我在使用输出重定向时发现了这种非常奇怪的csh行为。 我有以下脚本:

#! /bin/csh
set dirs = "."
set files = "`find "'"$dirs"'" -type f |& grep -v '^find: '`"
echo "-----------WITH &-----------------------"
echo "ARRAY:" $files
echo "FIRST ELEMENT FROM ARRAY1:" $files[1]

set files2 = "`find "'"$dirs"'" -type f`"
echo "------------WITHOUT &-----------------------"
echo "ARRAY2" $files2
echo "FIRST ELEMENT SECOND ARRAY" $files2[1]

现在如果你运行它,一切都很好。结果是:

-----------WITH &-----------------------
ARRAY: ./.netscape/preferences.js ...
FIRST ELEMENT FROM ARRAY1: ./.netscape/preferences.js
------------WITHOUT &-----------------------
ARRAY2 ./.netscape/preferences.js ...
FIRST ELEMENT SECOND ARRAY ./.netscape/preferences.js

但是当我像这样运行csh -x test.csh(它是较大脚本的一部分所以我必须以某种方式调试它)时,我得到了这个:

set dirs = .
set files = `find "$dirs" -type f |& grep -v '^find: '`
grep -v ^find: 
echo -----------WITH &-----------------------
-----------WITH &-----------------------
echo ARRAY: find . -type f ./.netscape/preferences.js ...
ARRAY: find . -type f ./.netscape/preferences.js ...
echo FIRST ELEMENT FROM ARRAY1: find . -type f
FIRST ELEMENT FROM ARRAY1: find . -type f               <----WHY?
set files2 = `find "$dirs" -type f`
find . -type f
echo ------------WITHOUT &-----------------------
------------WITHOUT &-----------------------
echo ARRAY2 ./.netscape/preferences.js ...
ARRAY2 ./.netscape/preferences.js ...
echo FIRST ELEMENT SECOND ARRAY ./.netscape/preferences.js
FIRST ELEMENT SECOND ARRAY ./.netscape/preferences.js

现在,在调试时会破坏脚本。我觉得这种行为很令人费解。有人可以解释为什么会发生这种情况以及如何避免它?

(不要发布无用的评论,我不应该使用csh,这是垃圾。我知道。但是我的大学强迫我使用它。)

编辑:我按照约翰·C的建议做了一切。我的输出是不同的。

bash2-2.05a$ csh -x test.csh 2>catch_stderr
-----------WITH &-----------------------
ARRAY: find . -type f ./test.csh ./ff.csh ./ff ./catch_stderr
FIRST ELEMENT FROM ARRAY1: find . -type f
------------WITHOUT &-----------------------
ARRAY2 ./test.csh ./ff.csh ./ff ./catch_stderr
FIRST ELEMENT SECOND ARRAY ./test.csh

bash2-2.05a$ cat catch_stderr 
set dirs = .
set files = `find "$dirs" -type f |& grep -v '^find: '`
grep -v ^find: 
echo -----------WITH &-----------------------
echo ARRAY: find . -type f ./test.csh ./ff.csh ./ff ./catch_stderr
echo FIRST ELEMENT FROM ARRAY1: find . -type f
set files2 = `find "$dirs" -type f`
find . -type f
echo ------------WITHOUT &-----------------------
echo ARRAY2 ./test.csh ./ff.csh ./ff ./catch_stderr
echo FIRST ELEMENT SECOND ARRAY ./test.csh

2 个答案:

答案 0 :(得分:1)

当你运行csh -x时,它会将每个命令回显给stderr。 如果你打开-x并像这样运行你的脚本....

>sh
sh-3.2$ csh -x test.csh 2>catch_stderr
-----------WITH &-----------------------
ARRAY: ./ff ./ff.csh ./test.csh
FIRST ELEMENT FROM ARRAY1: ./ff
------------WITHOUT &-----------------------
ARRAY2 ./ff ./ff.csh ./test.csh
FIRST ELEMENT SECOND ARRAY ./ff

sh-3.2$ cat catch_stderr
set dirs = .
set files = `find "$dirs" -type f |& grep -v '^find: '`
find . -type f
grep -v ^find:
echo -----------WITH &-----------------------
echo ARRAY: ./ff ./ff.csh ./test.csh
echo FIRST ELEMENT FROM ARRAY1: ./ff
set files2 = `find "$dirs" -type f`
find . -type f
echo ------------WITHOUT &-----------------------
echo ARRAY2 ./ff ./ff.csh ./test.csh
echo FIRST ELEMENT SECOND ARRAY ./ff

(将stderr重定向到文件)它的行为方式与没有-x的行为相同。 然后,您可以查看文件catch_stderr以查看跟踪信息。 当他们两个出来的时候,他们可以互相混淆一点。

答案 1 :(得分:1)

变量-x也适用于子壳。

因此,当子shell `find "'"$dirs"'" -type f |& grep -v '^find: '`被执行时,它会将find . -type f回显到stderr(这不会被2&gt;捕获,不知道为什么,但它不在我的情况下)然后执行它,但是|&amp; ;结合stderr和stdout,这个组合在脚本中被替换。所以find . -type f最终成为数组$ files中的第一个元素。

使用|&amp;时解决方案非常小心在`` csh中非常棘手。

John C也是对的。这实际上指出了我正确的方向。所以我赞成他的回答。他的bash可能会捕获子shell中的输出,所以我认为两个输出都可能出现。他的输出肯定是想要的行为。