dog*_*ane 93 shell bash io-redirection file-descriptors
我知道您可以创建一个文件描述符并将输出重定向到它。例如
exec 3<> /tmp/foo # open fd 3.
echo a >&3 # write to it
exec 3>&- # close fd 3.
Run Code Online (Sandbox Code Playgroud)
但是你可以在没有文件描述符的情况下做同样的事情:
FILE=/tmp/foo
echo a > "$FILE"
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个很好的例子,说明何时必须使用额外的文件描述符。
Gil*_*il' 59
大多数命令都有一个输入通道(标准输入,文件描述符 0)和一个输出通道(标准输出,文件描述符 1),或者对它们自己打开的几个文件进行操作(因此你向它们传递文件名)。(这是标准错误 (fd 2) 的补充,它通常会一直过滤到用户。)但是,有时将命令用作来自多个源或多个目标的过滤器会很方便。例如,这里有一个简单的脚本,它将文件中的奇数行与偶数行分开
while IFS= read -r line; do
printf '%s\n' "$line"
if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt
Run Code Online (Sandbox Code Playgroud)
现在假设您想对奇数行和偶数行应用不同的过滤器(但不将它们重新放在一起,这将是一个不同的问题,通常从 shell 中不可行)。在 shell 中,你只能通过管道将一个命令的标准输出传送到另一个命令;要通过管道传输另一个文件描述符,您需要先将其重定向到 fd 1。
{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt
Run Code Online (Sandbox Code Playgroud)
另一个更简单的用例是过滤命令的错误输出。
exec M>&N将文件描述符重定向到脚本的其余部分的另一个文件描述符(或直到另一个此类命令再次更改文件描述符)。exec M>&N和之间的功能有些重叠somecommand M>&N。该exec形式更强大,因为它不必是嵌套:
exec 8<&0 9>&1
exec >output12
command1
exec <input23
command2
exec >&9
command3
exec <&8
Run Code Online (Sandbox Code Playgroud)
其他可能感兴趣的示例:
还有更多例子:
io-redirectionfile-descriptorsPS 这是一个令人惊讶的问题,来自该网站上使用通过 fd 3 重定向的最受好评帖子的作者!
For*_*rdi 20
这是使用额外 FD 作为 bash 脚本聊天控制的示例:
#!/bin/bash
log() {
echo $* >&3
}
info() {
echo $* >&4
}
err() {
echo $* >&2
}
debug() {
echo $* >&5
}
VERBOSE=1
while [[ $# -gt 0 ]]; do
ARG=$1
shift
case $ARG in
"-vv")
VERBOSE=3
;;
"-v")
VERBOSE=2
;;
"-q")
VERBOSE=0
;;
# More flags
*)
echo -n
# Linear args
;;
esac
done
for i in 1 2 3; do
fd=$(expr 2 + $i)
if [[ $VERBOSE -ge $i ]]; then
eval "exec $fd>&1"
else
eval "exec $fd> /dev/null"
fi
done
err "This will _always_ show up."
log "This is normally displayed, but can be prevented with -q"
info "This will only show up if -v is passed"
debug "This will show up for -vv"
Run Code Online (Sandbox Code Playgroud)
小智 8
在命名管道 (fifos) 的上下文中,使用附加文件描述符可以启用非阻塞管道行为。
(
rm -f fifo
mkfifo fifo
exec 3<fifo # open fifo for reading
trap "exit" 1 2 3 15
exec cat fifo | nl
) &
bpid=$!
(
exec 3>fifo # open fifo for writing
trap "exit" 1 2 3 15
while true;
do
echo "blah" > fifo
done
)
#kill -TERM $bpid
Run Code Online (Sandbox Code Playgroud)
请参阅:命名管道在脚本中过早关闭?
额外的文件描述符适用于当您想在变量中捕获标准输出但仍想写出到屏幕时,例如在 bash 脚本用户界面中
arg1 string to echo
arg2 flag 0,1 print or not print to 3rd fd stdout descriptor
function ecko3 {
if [ "$2" -eq 1 ]; then
exec 3>$(tty)
echo -en "$1" | tee >(cat - >&3)
exec 3>&-
else
echo -en "$1"
fi
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这是使用附加文件描述符似乎合适的另一种情况(在 Bash 中):
env -i bash --norc # clean up environment
set +o history
read -s -p "Enter your password: " passwd
exec 3<<<"$passwd"
mycommand <&3 # cat /dev/stdin in mycommand
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
55394 次 |
| 最近记录: |