題 在bash管道行之間執行命令......?


我想運行一系列管道命令,這些命令可以進行大量的語音處理。它在偽代碼中看起來如下:

command1 | command2 | command3

在command2和command3中,都將前一個命令的輸出作為輸入(常規stdin / stdout行為)。

現在我想在command1之後執行另一個command1.1,它不會連接到command1和command2之間的運行管道,除非它在command1完全完成之前不能運行。

command1 [; after that run command1.1, even if command2 and command3 are still busy] command2 command3

但是我不知道如何在bash中這樣做。我已經嘗試過tee,但這使得命令在管道構建後立即運行。有任何想法嗎?

謝謝!


4
2018-01-18 17:27


起源




答案:


您可以將其重定向到子shell。

command1 & > >(command2 | command3) &
wait $!      # Wait end of process $! (actually the pid of command1)
command_1.1     

另一種方法是創建命名管道 FIFO
腳本應該類似於

MYFIFO=/tmp/myfifo.$$
rm -f $MYFIFO
mkfifo $MYFIFO
command1 > $MYFIFO &
MYPROGRAM_PID=$!
cat $MYFIFO  | command2 | command3 &
wait $MYPROGRAM_PID   # Wait end of process $MYPROGRAM_PID
command_1.1     

4
2018-01-18 18:17





關於這一點的重要部分是“之後” - UNIX管道在“之後”的唯一概念是,它們通常關閉,但它們將在第一個命令之後執行 開始,不是在ist之後 結束

所以你需要做的是使用一個shell腳本 - 這個東西確實具有“一個接一個”的概念:

echo 'command1' > myscript.sh
echo 'command1.1 >&2' >> myscript.sh
chmod 755 myscript.sh

(當然你可以使用自己喜歡的編輯器來實現),然後運行

myscript.sh | command2 | command3

現在發生的是,輸出 command1 將是shell腳本的輸出,因此您的管道工作。在你的腳本里面,輸出 command1.1 將被重定向到腳本的STDERR,因此它不會發送到管道,而是發送到終端


4
2018-01-18 18:05



歐根,應該是第二個迴聲 echo 'command1.1 >&2' >> myscript.sh - Romeo Ninov
可能更好 ./myscript.sh 比 myscript.sh;通常,出於安全原因,當前目錄不包含在路徑中... - Hastur
@RomeoNinov謝謝 - 修復! - Eugen Rieck
@Hastur我遺漏了所有的姿勢 - 從我認為的OQ,海報知道他的方式 - Eugen Rieck
@EugenRieck我同意,這不適合你或cunei。我們都希望答案對其他讀者也有用:-)而且,也許,其中一個人可能會在第一眼就錯過了某個命令之間的區別。 PATH和一個腳本,即使 可執行 (chmod 755)是在當前目錄中,默認情況下是從 PATH。 - Hastur


最簡單的結構是:

(command1 ; command1.1) | command2 | command3

這有兩個潛在的問題。如果 command1.1 在stdout上產生任何輸出,它將通過管道發送。另外 command2 在stdin之前不會看到EOF command1.1 已經完成了。

如果最初在stdout和stderr文件描述符都指向同一文件結構的上下文中調用管道,那麼有一種簡單的方法可以解決這兩個問題:

(command1 ; exec 1>&2 command1.1) | command2 | command3

這將導致command1.1的stdout指向stderr,而stderr沒有被管道重定向。

如果最初stdout和stderr可能是兩個不同的文件描述符,則可以通過臨時存儲另一個文件描述符號中的初始stdout來使用上述方法。所以除非你絕對需要保持stdout和stderr command1.1 分開,我不會採取這種方法。

為了完整性,如果你想這樣做,它可能看起來像這樣:

(((exec 9>&- command1) ; exec 1>&9 9>&- command1.1) | exec 9>&- command2 | exec 9>&- command3) 9>&1

2
2018-01-18 20:01