在Bash中如何重定向stdin/stdout的命令序列?
我现在有一个Bash命令正在执行(通过Python的subprocess.Popen
),它是从stdin
读取数据,处理一些事情,然后输出到stdout
。大概是这样的:
pid = subprocess.Popen( ["-c", "cmd1 | cmd2"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
shell =True )
output_data = pid.communicate( "input data\n" )
现在,我想做的是在同一个子shell中执行另一个命令,这个命令会在下一个命令执行之前改变一些状态,所以我的命令行现在(从概念上讲)会变成:
cmd0; cmd1 | cmd2
在这种情况下,有没有办法让输入发送到cmd1
而不是cmd0
呢?我假设输出会包含cmd0
的输出(这应该是空的),然后是cmd2
的输出。
cmd0
其实不应该从stdin
读取任何东西,这在这种情况下有影响吗?
我知道这可能只是个笨办法,我想在不太改变其他代码的情况下插入cmd0
。不过,如果有更好的方法,我也很乐意听听建议。
3 个回答
0
好的,我想我可以把 stdin
文件描述符复制到一个临时的地方,然后把它关闭,接着运行 cmd0
,最后在运行 cmd1
之前再把它恢复过来:
exec 0>&3; exec 0<&-; cmd0 ; exec 3>&0 ; cmd1 | cmd2
不过我不确定这样重定向 stdin
是否可行,现在也没法测试。
1
我觉得你不需要做什么特别的事情。如果cmd0没有修改标准输入(stdin),那么它会保持原样,供cmd1使用。你可以自己试试看:
ls | ( echo "foo"; sed 's/^/input: /')
(这里用ls
作为一个随便的命令,来生成几行输入给管道使用)
当然,额外的管道连接到cmd2也不会影响输入。
4
在一个子进程中执行 cmd0 和 cmd1,并把 /dev/null 作为 cmd0 的输入:
(cmd0 </dev/null; cmd1) | cmd2