2014-09-10 96 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

這是不可能的,因爲配管連接進程同時運行,而不是按順序。換句話說,只要你得到第一個命令的退出狀態,所有的輸出都已經通過管道發送了。一個管道總是連接兩個正在運行的進程,並且正在運行的進程還沒有退出狀態。