有一些命令会过滤或作用于输入,然后将其作为输出传递,我认为通常是这样stdout
- 但有些命令只会接受stdin
并对其执行任何操作,并且不输出任何内容。
我最熟悉 OS X,因此立即想到的两个是pbcopy
和pbpaste
- 这是访问系统剪贴板的方法。
无论如何,我知道如果我想获取 stdout 并将输出吐出到两个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
),但我希望有一种方法可以内联、简洁地完成此操作,无需事先设置:)
答案1
您可以使用tee
并处理替换:
cat file.txt | tee >(pbcopy) | grep errors
这会将 的所有输出发送到cat file.txt
,并且您只能在控制台上pbcopy
获得 的结果。grep
您可以在该tee
部分中放置多个进程:
cat file.txt | tee >(pbcopy) >(do_stuff) >(do_more_stuff) | grep errors
答案2
您可以向 指定多个文件名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
答案3
只需玩一下进程替换即可。
mycommand_exec |tee >(grep ook > ook.txt) >(grep eek > eek.txt)
grep
mycommand_exec
是两个二进制文件,其输出与其流程特定的输入相同。