BASH脚本STDIN为空时如何停止读取避免阻塞继续执行
问题根因
你现有代码的逻辑顺序错误,且cat <&0默认会阻塞等待标准输入:只要标准输入连接的是终端(即无参数直接执行脚本、没有管道/重定向传入数据流的场景),命令会一直等待用户手动输入,永远不会走到后续的帮助提示分支。你把帮助输出的逻辑写在了elif [[ -n "$stream" ]]分支下,这个分支在无参数场景下根本没有机会触发。
解决方案
用-t 0测试条件判断标准输入是否连接到终端,按优先级拆分三个处理场景即可,不需要提前把输入流全读入变量(直接调用cat原样输出性能更好,也不会卡):
#!/bin/bash HELP_INFO="I am the help: I just print what you say." # 1. 传入文件路径参数的场景:直接读取指定文件输出 if [[ $# -gt 0 ]]; then if [[ -r "$1" ]]; then cat -- "$1" else echo "Error: Cannot read file $1" >&2 exit 1 fi # 2. 无参数但标准输入不是终端:说明有管道/重定向传入数据流,直接原样输出 elif [[ ! -t 0 ]]; then cat # 3. 无参数且标准输入连接终端:没有传入数据流,输出帮助提示 else echo "$HELP_INFO" fi
关键说明
-t 0是shell内置的测试条件,作用是检测文件描述符0(标准输入)是否关联到终端设备:返回真时说明用户是直接在终端执行脚本,没有绑定任何输入数据流,此时直接输出帮助即可,完全不会触发阻塞等待输入的问题。- 直接调用
cat处理输入流,比把所有内容存到变量再输出的写法更省内存,面对大文件或者长数据流也不会有性能问题。 - 给文件加了
-r可读校验,避免传入不存在或者无权限的文件时报无意义的错误。
所有要求的场景均可正常运行:
- 执行
cat myfile.txt:直接输出文件内容hello world! - 执行
cat myfile.txt | ./myscript.sh:正常读取管道流输出hello world! - 执行
./myscript.sh myfile.txt:读取参数指定的文件输出hello world! - 直接执行
./myscript.sh:立即输出帮助提示,不会卡住等待输入。
内容的提问来源于stack exchange,提问作者ampinzonv
相关产品推荐
相关产品推荐

