Bash:在脚本中动态重定向标准输入

Get*_*ree 29 linux bash shell io-redirection

我试图这样做来决定是否将stdin重定向到文件:

[ ...some condition here... ] && input=$fileName || input="&0"
./myScript < $input
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为当变量$ input为"&0"时,bash会将其解释为文件名.

但是,我可以这样做:

if [ ...condition... ];then
    ./myScript <$fileName
else
    ./myScript
Run Code Online (Sandbox Code Playgroud)

问题是./myScript实际上是一个我不想复制的长命令行,也不想为它创建一个函数,因为它也不长(它不值得).

然后我突然想到这样做:

[ ...condition... ] && input=$fileName || input=  #empty
cat $input | ./myScript
Run Code Online (Sandbox Code Playgroud)

但这需要再运行一个命令和一个管道(即子shell).
还有另一种更简单,更有效的方法吗?

Pau*_*ce. 24

首先,stdin是文件描述符0(零)而不是1(stdout).

您可以像这样有条件地复制文件描述符或使用文件名:

[[ some_condition ]] && exec 3<"$filename" || exec 3<&0

some_long_command_line <&3
Run Code Online (Sandbox Code Playgroud)

请注意,exec如果条件为false 第一个exec失败,则显示的命令将执行第二个命令.如果您不希望有可能失败,那么您应该使用if/ else:

if [[ some_condition ]]
then
    exec 3<"$filename"
else
    exec 3<&0
fi
Run Code Online (Sandbox Code Playgroud)

但是如果第一次重定向失败(在条件为真之后),则后续文件描述符3的重定向将失败.


eph*_*ent 7

(
    if [ ...some condition here... ]; then
        exec <$fileName
    fi
    exec ./myscript
)
Run Code Online (Sandbox Code Playgroud)

在子shell中,有条件地重定向stdin并执行脚本.

  • +1.如果它包含空格,请在`$ fileName`周围加上引号. (3认同)

Ign*_*ams 7

标准输入也可以由特殊设备文件表示/dev/stdin,因此将其用作文件名将起作用.

file="/dev/stdin"
./myscript < "$file"
Run Code Online (Sandbox Code Playgroud)

  • 听起来可能是某种错误的配置;/ dev / stdin应该(几乎)始终可用。特别是,我相信Linux和Solaris都将它实现为与`/ proc / self / fd / 0`的符号链接,而我唯一想到的问题就是UID是否已更改。 (2认同)