多年来我一直试图理解这个概念,但目前对此的了解并不完整。
这里的任何人都可以制作一种教程或很好的解释,并举例说明如何
fd
fd
fd
fd
我已阅读https://www.gnu.org/software/bash/manual/html_node/Redirections.html和man bash
,但不清楚,根本没有具体且可理解的示例。
如果有人能很好地解释它,这将是一个有价值的答案,不仅对我而言。语法大多数时候都有点混乱。
有时需要exec
,有时不需要。
Bourne-like shell 的一些翻译:
\n系统调用 | 外壳接口 | 贝壳 | 评论 |
---|---|---|---|
open("file", O_RDONLY) | exec 3< file | 全部 | 此处在 fd 3\xc2\xb9 上打开 |
open("file", O_RDONLY) | exec {fd}< file | zsh ksh93 bash | fd 返回于$fd \xc2\xb2 |
open("file", O_WRONLY|O_TRUNC|O_CREAT) | exec 3> file | 全部 | \xc2\xb3 |
open("file", O_WRONLY|O_APPEND|O_CREAT) | exec 3>> file | 全部 | 4 |
open("file", O_RDWR|O_CREAT) | exec 3<> file | 全部 | |
open("file", ...) | sysopen ... | 桀骜 | 在 zsh/系统模块中 |
dup2(4, 5) | exec 5>&4 | 全部 | 与...一样exec 5<&4 |
dup(4) | exec {fd}>&4 | zsh ksh93 bash | fd 返回$fd |
write(4, data, length) | print -rnu4 -- "$data" | 克什兹什 | bash 还有一个可加载的print 内置示例5 |
write(...) | syswrite ... | 桀骜 | 在 zsh/系统模块中 |
read(4, var...) | sysread -i 4 ... var | 桀骜 | zsh/system 在模块中 |
read(4, var...) | IFS= read -ru4 ... var | ksh zsh bash | 读取一行。谨防限制。5 |
close(4) | exec 4>&- | 全部 | 或者exec 4<&- |
lseek(4, 123, SEEK_SET) | exec 4>#((123)) | 克什93 | |
lseek(4, 123, SEEK_CUR) | exec 4>#((CUR + 123)) | 克什93 | |
lseek(4, 123, SEEK_END) | exec 4>#((EOF + 123)) | 克什93 | |
lseek(...) | sysseek ... | 桀骜 | 在 zsh/系统模块6中 |
pipe() | exec 4>>|5 | 亚什 | fd 4 写端,5 读端 |
fstat(4, var) | zstat -f 4 -H var | 桀骜 | 在 zsh/stat 模块中 |
select(...) | zselect ... | 桀骜 | 在 zsh/zselect 模块中 |
zsh 还具有一些zsh/net/socket
, zsh/net/tcp
,zsh/zpty
模块来创建操作其他类型的 fd。
使用exec
更改 shell 进程的文件描述符。然而,大多数时候,您只想更改其他命令的文件描述符,例如仅在 fd 1 (stdout) 上打开ls -l dir/ > file
(缩写)或一段代码:ls -l dir/ 1> file
file
ls
{\n echo Some Header\n ls -l dir/\n} 1> file 2>> error.log\n
Run Code Online (Sandbox Code Playgroud)\nfoo | bar
在并发进程中执行pipe()
7后跟一些dup2()
s 或等效项和close()
s,因此将运行的进程的 fd 1foo
转到管道的写入端,而 fd 0 或bar
转到读取端。其他使用或可能使用管道的 shell 结构包括命令替换 ( var=$(cmd)
, var=`cmd`
)、类似 Korn 的 shell 进程替换 ( foo <(bar) >(baz)
)、协同进程、yash 进程重定向。
ksh93 和 bash 中的 \xc2\xb9 ,如果file
是/dev/tcp|udp/host/port
,它不会执行真正的打开,而是创建一个网络套接字。
\xc2\xb2 对于其他>
, >>
, <>
,>
运算符也可以这样做
\xc2\xb3 如果noclobber
打开该选项,O_EXCL
如果目标是常规文件,则添加 a,可以使用>|
或>!
运算符绕过,具体取决于 shell
4在 Bourne shell 中,没有O_APPEND
,但是 shell 在 open 后求到底
5在其他 shell 中,您始终可以执行printf %s "$var" >&4
. 这不会写入 fd 4,而是写入 fd 1,经过一段时间后dup2(4, 1)
实际上达到了相同的目标。对于 也一样IFS= read -r line <&4
。
6另请参阅systell(fd)
返回 fd 位置的数学函数,它是另一个接口lseek()
7某些使用socketpair()
s 而不是管道的系统上的 ksh93 除外。对于其他一些使用管道的结构也是如此。