测试 stdin 是文件还是管道还是 tty
Testing whether stdin is a file vs. a pipe vs. a tty
我知道 bash 和 zsh,可以使用例如[ -t 1 ]
确定 STDIN 是否为交互式 tty 会话。
但是,似乎没有办法测试 stdin 是从文件重定向还是从命令输入:
foo < ./file
bar | foo
有什么方法可以检测出这两者之间的区别吗?另外,是否有任何方法可以获取被重定向的文件的路径(在 /proc/self 之外,这在 macOS 上不可用)?
您可以检查 /dev/stdin
是普通文件还是管道:
$ cat tmp.sh
#!/bin/bash
if [ -f /dev/stdin ]; then
echo "file"
elif [ -p /dev/stdin ]; then
echo "pipe"
fi
$ bash tmp.sh < foo.txt
file
$ echo foo | bash tmp.sh
pipe
不过,这取决于 /dev/stdin
在您的文件系统中。
您也可以使用 stat
命令,该命令将 return 没有文件名参数的标准输入的信息。正如您提到的,您使用的是 macOS,您可以使用 %HT
格式:
$ stat -f %HT
Character Device
$ stat -f %HT < foo.txt
Regular File
$ echo foo | stat -f %HT
Fifo File
我知道 bash 和 zsh,可以使用例如[ -t 1 ]
确定 STDIN 是否为交互式 tty 会话。
但是,似乎没有办法测试 stdin 是从文件重定向还是从命令输入:
foo < ./file
bar | foo
有什么方法可以检测出这两者之间的区别吗?另外,是否有任何方法可以获取被重定向的文件的路径(在 /proc/self 之外,这在 macOS 上不可用)?
您可以检查 /dev/stdin
是普通文件还是管道:
$ cat tmp.sh
#!/bin/bash
if [ -f /dev/stdin ]; then
echo "file"
elif [ -p /dev/stdin ]; then
echo "pipe"
fi
$ bash tmp.sh < foo.txt
file
$ echo foo | bash tmp.sh
pipe
不过,这取决于 /dev/stdin
在您的文件系统中。
您也可以使用 stat
命令,该命令将 return 没有文件名参数的标准输入的信息。正如您提到的,您使用的是 macOS,您可以使用 %HT
格式:
$ stat -f %HT
Character Device
$ stat -f %HT < foo.txt
Regular File
$ echo foo | stat -f %HT
Fifo File