Shell

如何將標準輸出發送到多個命令?

  • July 29, 2021

有一些命令過濾或作用於輸入,然後將其作為輸出傳遞,我認為通常是這樣stdout- 但有些命令只會接受stdin並做任何他們用它做的事情,並且什麼也不輸出。

我對 OS X 最熟悉,因此立即想到兩個是pbcopypbpaste- 是訪問系統剪貼板的方法。

無論如何,我知道如果我想獲取標準輸出並將輸出吐到兩者stdout和一個文件中,那麼我可以使用該tee命令。而且我知道一點點xargs,但我不認為那是我正在尋找的。

我想知道如何拆分stdout以在兩個(或更多)命令之間進行。例如:

cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors

可能有一個比那個更好的例子,但我真的很想知道如何將標準輸出發送到一個不中繼它的命令,同時避免stdout被“靜音”——我不是在問如何cat文件和grep它的一部分並將其複製到剪貼板 - 具體的命令並不重要。

另外-我不是在問如何將其發送到文件,而且stdout-這可能是一個“重複”的問題(對不起),但我做了一些查找,只能找到類似的詢問如何在標準輸出和文件之間拆分的問題- 這些問題的答案似乎是tee,我認為這對我不起作用。

最後,您可能會問“為什麼不把 pbcopy 放在管道鏈中的最後一件事呢?” 我的回答是 1)如果我想使用它並且仍然在控制台中看到輸出怎麼辦?2)如果我想使用兩個stdout在處理輸入後不輸出的命令怎麼辦?

哦,還有一件事——我意識到我可以使用tee命名管道(mkfifo),但我希望有一種方法可以簡潔地內聯完成,而無需事先設置:)

您可以tee為此使用和處理替換:

cat file.txt | tee >(pbcopy) | grep errors

這將發送cat file.txtto的所有輸出pbcopy,並且您只能grep在控制台上獲得結果。

您可以在零件中放置多個程序tee

cat file.txt | tee >(pbcopy) >(do_stuff) >(do_more_stuff) | grep errors

您可以為 指定多個文件名tee,此外,標準輸出可以通過管道傳輸到一個命令中。要將輸出分派給多個命令,您需要創建多個管道並將每個管道指定為tee. 有幾種方法可以做到這一點。

流程替代

如果你的 shell 是 ksh93、bash 或 zsh,你可以使用程序替換。這是一種將管道傳遞給需要文件名的命令的方法。shell 創建管道並將文件名傳遞/dev/fd/3給命令。該數字是管道連接到的文件描述符。一些 unix 變體不支持/dev/fd; 在這些上,改用命名管道(見下文)。

tee >(command1) >(command2) | command3

文件描述符

在任何 POSIX shell 中,您都可以顯式使用多個文件描述符。這需要一個支持 的 unix 變體/dev/fd,因為除一個輸出之外的所有輸出都tee必須按名稱指定。

{ { { tee /dev/fd/3 /dev/fd/4 | command1 >&9;
   } 3>&1 | command2 >&9;
 } 4>&1 | command3 >&9;
} 9>&1

命名管道

最基本和可移植的方法是使用命名管道。缺點是你需要找到一個可寫的目錄,創建管道,然後清理。

tmp_dir=$(mktemp -d)
mkfifo "$tmp_dir/f1" "$tmp_dir/f2"
command1 <"$tmp_dir/f1" & pid1=$!
command2 <"$tmp_dir/f2" & pid2=$!
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
rm -rf "$tmp_dir"
wait $pid1 $pid2

引用自:https://unix.stackexchange.com/questions/28503