2014-09-10 98 views
1

试图才达到类似:管道到不同的命令基于退出状态在bash

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

例如管道到不同的命令,取决于退出状态。

上述〔实施例没有作品,例如:

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

ls的出口站点非零时,可能实现运行command_no

我知道,这是可能实现像

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" 

,但我想避免辅助变量,也没有临时文件。有可能的?

+2

在'command'退出之前需要设置管道,对吧?你怎么能根据不存在的退出状态切换管道的目的地? – 2014-09-10 18:51:49

+1

只是想通了 - 因为**我不知道命令的退出状态**,因为它仍在运行...... – kobame 2014-09-10 18:52:08

+1

如果shell运行同一管道中的所有组件shell,理论上类似'{command1&pid = $ !; } | {wait $ pid && command_ok || command_no; ''可以工作。 POSIX并不禁止这样做,但我不知道有这样做的shell。 – chepner 2014-09-10 18:54:17

回答

3

如上所述,如果不涉及获取临时文件,则无法执行此操作:在原始命令运行完成之前,需要设置管道。然而,一个临时文件做起来很简单:

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

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

3

这是不可能的,因为配管连接进程同时运行,而不是按顺序。换句话说,只要你得到第一个命令的退出状态,所有的输出都已经通过管道发送了。一个管道总是连接两个正在运行的进程,并且正在运行的进程还没有退出状态。