更多 Bash 重定向
发表于 2009 年 10 月 6 日
每个人都见过 bash 命令中的重定向,这很常见,但是 bash 也允许你在定义函数时定义重定向。 这会导致重定向在每次调用该函数时被评估/执行。 此功能实际上并没有提供任何新功能,只是另一种表达现有功能的方式。
此语法很简单,只需将重定向附加到函数定义的末尾
function testy()
{
...
} < testy.in > testy.out 2> testy.err
现在无论何时调用函数testy它的输入将来自testy.in,它的输出将转到testy.out,并且任何错误都将转到testy.err.
由于重定向是在调用函数时评估的,因此重定向可以使用变量,并且变量也在调用函数时进行评估。 所以你可以这样做
#!/bin/bash
function testy()
{
echo testy westy
} >$out
out=jj1
testy
out=jj2
testy
这会导致函数的输出在每次调用时转到不同的文件。 第一次调用的输出转到jj1,第二次转到jj2:
$ bash j.sh; more jj?
::::::::::::::
jj1
::::::::::::::
testy westy
::::::::::::::
jj2
::::::::::::::
testy westy
正如我之前提到的,这里没有任何真正的新功能,你也可以用这种方式完成同样的事情
#!/bin/bash
function testy()
{
echo testy westy
}
testy >jj1
testy >jj2
此功能的一种可能用途可能是将所有代码放在main函数中,然后重定向它的错误输出,以确保它始终被捕获
#!/bin/bash
log=kk
function error()
{
echo "$*" >&2
}
function testy()
{
error testy westy
}
function testy2()
{
error testy2 westy2
}
function main()
{
testy
testy2
} 2>$log
main
运行此程序会产生
$ bash k.sh ;cat kk
testy westy
testy2 westy2
由于 bash 还允许在{...}块/列表 上包含重定向,因此你可以使用以下方法完成相同的事情
#!/bin/bash
log=mm
function error()
{
echo "$*" >&2
}
function testy()
{
error testy westy
}
function testy2()
{
error testy2 westy2
}
{
testy
testy2
} 2>$log
你也可以在(...)块/列表 上使用重定向,但这会导致命令在子 shell 中执行,这没有必要,并且可能会导致问题,因为子 shell 是一个不同的进程。
如果你想知道是否可以在实际调用中覆盖重定向,答案是否定的。 如果你尝试覆盖它们,发生的一切都是调用中的重定向首先被执行/评估,然后函数定义中的重定向替换它们。 例如,在以下代码中
#!/bin/bash
function testy()
{
echo testy westy
} >nn1
testy >nn2
调用中指定的输出文件 (nn2) 被创建,但没有任何内容写入其中。
另请注意,管道“重定向”不起作用,但 here documents (此处文档) 起作用
#!/bin/bash
function testy()
{
while read line
do
echo $line
done
} <<EOF
hello
there
EOF
testy
运行此程序会产生
$ bash o.sh
hello
there