在问题中“测试文件描述符是否有效”,寻求测试来测试文件描述符是否打开。
答案都集中在测试文件描述符是否打开输出,但是如何测试文件描述符是否打开输入?
这是在另一个问题的答案的评论线程中出现的,答案是这样解释的:
if [ -n "$1" ]; then
# read input from file "$1" (we're assuming it exists)
elif [ ! -t 0 ]; then
# read input from standard input (from pipe or redirection)
else
# no input given (we don't want to read from the terminal)
fi
问题是如果文件描述符打开则测试为[ ! -t 0 ]
真-t
和与终端关联。如果测试为假,则描述符为任何一个关闭,或者不与终端关联(即我们正在从管道或重定向中读取)。因此,测试并[ ! -t 0 ]
不能保证文件描述符有效。
如何确定它是否有效(这样read
就不会抱怨)或是否已关闭?
答案1
read(fd, 0, 0)
在 C 语言中,使用或可以很容易地进行检查(fcntl(fd, F_GETFL) & O_WRONLY) == 0
。我无法欺骗任何标准实用程序来执行此操作,因此这里有一些可能的解决方法。
在 Linux 上,您可以使用/proc/PID/fdinfo/FD
:
if [ ! -d "/proc/$$/fd/$fd" ] && grep -sq '^flags.*[02]$' "/proc/$$/fdinfo/$fd"; then
echo "$fd" is valid for input
fi
在 OpenBSD 和 NetBSD 上,您可以将/dev/fd/FD
anddd
与零计数一起使用:
if dd if=/dev/fd/3 count=0 3<&"$fd" 2>/dev/null; then
echo "$fd" is valid for input
fi
在 FreeBSD 上,默认情况下仅提供前 3 个 fd /dev/fd
;;您应该安装fdescfs(5)
在/dev/fd
或:
if (dd if=/dev/fd/0 count=0 <&"$fd") 2>/dev/null; then
echo "$fd" is valid for input
fi
笔记:
在某些系统上,bash
它的模拟/dev/fd/FD
,因此cat </dev/fd/7
可能与cat /dev/fd/7
.同样的警告适用于gawk
.
read(2)
长度为 0(或者其标志中open(2)
没有长度)的 A将O_TRUNC
不是更新访问时间或任何其他时间戳。
在 Linux 上,read(2)
即使打开了目录,a 也总是会失败没有旗帜O_DIRECTORY
。在其他 Unix 系统上,可以像读取另一个文件一样读取目录。
这标准未指定是否dd count=0
不复制任何块或全部来自文件的块:前者是 GNU dd ( gdd
) 和dd
*BSD 的行为。
答案2
这似乎适用于 linux bash
if read -u $fd -n 0 -t 0 2>/dev/null
then
....
fi