根据bash中的退出状态管道到不同的命令

时间:2014-09-10 18:45:40

标签: bash

尝试实现以下目标:

command | { [[ ${PIPESTATUS[0] == 0 ]] && cmd_pipe_success || cmd_pipe_failed ; }

e.g。管道到不同的命令,具体取决于退出状态。

上述例子不起作用,例如:

command_ok() { sed 's/^/OK /'; }
command_no() { sed 's/^/NO /'; }

touch x
ls -l x 2>&1 | { [[ ${PIPESTATUS[0]} == 0 ]] && command_ok || command_no ; }
rm x
ls -l x 2>&1 | { [[ ${PIPESTATUS[0]} == 0 ]] && command_ok || command_no ; }

都打印OK,因此在两种情况下都会运行command_ok

command_no的退出状态非零时,是否可以实现运行ls

我知道,有可能实现像

command_ok() { sed 's/^/OK /'; return 0; }
command_no() { sed 's/^/NO /'; return 0; }

touch x
res=$(ls -l x 2>&1)
[[ $? == 0 ]] && command_ok <<<"$res" || command_no <<<"$res"

rm x
res=$(ls -l x 2>&1)
[[ $? == 0 ]] && command_ok <<<"$res" || command_no <<<"$res"

但我希望避免辅助变量,也不想临时文件。有可能吗?

4 个答案:

答案 0 :(得分:3)

如前所述,如果没有获得临时文件,就无法做到这一点:需要在原始命令运行完毕之前设置管道。但是,使用临时文件执行此操作非常简单:

TEMPFILE=$(mktemp)
if command > $TEMPFILE; then
  command_ok < $TEMPFILE
else
  command_no < $TEMPFILE
fi
rm $TEMPFILE

答案 1 :(得分:3)

这是不可能的,因为与管道连接的进程同时运行,而不是顺序运行。换句话说,只要获得第一个命令的退出状态,就会通过管道发送所有输出。管道始终连接两个正在运行的进程,并且正在运行的进程尚未具有退出状态。

答案 2 :(得分:2)

管道的组件并行运行(通常在单独的shell中),因此在运行第二个命令之前无法确定第一个命令是否成功。

答案 3 :(得分:0)

尝试使用TRAP命令。您可以根据命令的结果或脚本的返回值执行不同的操作。

例如,您可以说trap 'echo 'Exiting...'; exit' SIGQUIT

以下是一个充满示例的页面,其中包括一些可能有用的更多参与:http://www.ibm.com/developerworks/aix/library/au-usingtraps/