如果要覆蓋使用bash文件,這很容易Bash,使用文件描述符覆蓋?
echo "Hello world" > hosts
這似乎不是一個文件描述符
$ exec 3<> hosts
$ echo "Hello world" >&3
$ cat hosts
Hello world
$ echo "Hello world" >&3
$ cat hosts
Hello world
Hello world
如果要覆蓋使用bash文件,這很容易Bash,使用文件描述符覆蓋?
echo "Hello world" > hosts
這似乎不是一個文件描述符
$ exec 3<> hosts
$ echo "Hello world" >&3
$ cat hosts
Hello world
$ echo "Hello world" >&3
$ cat hosts
Hello world
Hello world
這是正確的工作。打開文件的模式在shell調用open(2)
時確定。當您使用FD(任何語言)時,打開文件時設置的標誌是shared between open FDs。在你的情況下,O_TRUNC
只能在文件實際打開時指定。
重要的是要知道的是,只有使用<file
,>file
或類似方法打開文件時,才能確定模式和各種標誌。使用&
修飾符複製FD基本上會創建指向原始FD的「別名」,並保留與原始狀態完全相同的狀態。截斷文件需要重新打開它。
這是我的調試功能,如果你想玩弄容易文件描述符:
lsfd() {
local ofd=${ofd:-2} target=${target:-$BASHPID}
while [[ $1 == -* ]]; do
if [[ -z $2 || $2 == *[![:digit:]]* ]]; then
cat
return 1
fi
case ${1##+(-)} in
u)
shift
ofd=$1
shift
;;
t)
shift
target=$1
shift
;;
h|\?|help)
cat
return
esac
done <<EOF
USAGE: ${FUNCNAME} [-h|-?|--help] [-u <fd>] [ -t <PID> ] [<fd1> <fd2> <fd3>...]
This is a small lsof wrapper which displays the open
file descriptors of the current BASHPID. If no FDs are given,
the default FDs to display are {0..20}. ofd can also be set in the
environment.
-u <fd>: Use fd for output. Defaults to stderr. Overrides ofd set in the environment.
-t <PID>: Use PID instead of BASHPID. Overrides "target" set in the environment.
EOF
IFS=, local -a 'fds=('"${*:-{0..20\}}"')' 'fds=("${fds[*]}")'
lsof -a -p $target -d "$fds" +f g -- >&${ofd}
}
我喜歡不關閉標準輸入,因爲這有時會引起問題,所以它就會先保存。
$ ({ lsfd 3; cat <&3; } {savefd}<&0 <<<'hi' 3>&0- <&"${savefd}")
COMMAND PID USER FD TYPE FILE-FLAG DEVICE SIZE/OFF NODE NAME
bash 920 ormaaj 3r REG LG 0,22 3 59975426 /tmp/sh-thd-8305926351 (deleted)
hi
正如你可以看到,即使FD 0使用3>&0-
運營商移動到3個,文件保持打開狀態O_RDONLY
。 >
或<
的選擇對於副本描述符是任意的,只用於確定操作員左側的FD省略時的默認值。
如果你確實想打開一個新的獨立的FD,這樣的事情可能工作:
$ ({
cat <&4 >/dev/null; lsfd 3 4; echo there >&4; cat </dev/fd/3
} {savefd}<&0 <<<'hi' 3>&0- 4<>/dev/fd/3 <&"${savefd}"
)
COMMAND PID USER FD TYPE FILE-FLAG DEVICE SIZE/OFF NODE NAME
bash 2410 ormaaj 3r REG LG 0,22 3 59996561 /tmp/sh-thd-8305914274 (deleted)
bash 2410 ormaaj 4u REG RW,LG 0,22 3 59996561 /tmp/sh-thd-8305914274 (deleted)
hi
there
現在FD 4是真的「重開」到FD 3指着文件,而不僅僅是複製(即使該文件已經如上所述已經是unlink(2)
'd)。首先使用cat
打開第一個FD 4並查找到最後,然後再向該文件寫入一行。同時,FD3的尋找位置仍然處於開始位置,因此整個文件可以被送到終端。
相同的原則可以適用於您的情況。
$ { echo 'Hello world'; echo 'hi' >/dev/fd/1; } >hosts; cat hosts
hi
或者甚至可能是更好的將是剛剛打開和關閉兩個命令兩次文件,且沒有exec
。
我寧願避免使用exec
只是爲了打開文件描述符,除非它是絕對必要的。你必須記得明確地關閉文件。如果您使用命令分組,文件將自動關閉自己,實際上給他們一個「範圍」。這在原理上類似於Python的with
聲明。這可能會阻止一些混淆。
也參見:
+1,非常好,但* IMO *你沒有*完全*回答OP的問題。 –
你不應該關閉並重新打開該FD的 「回聲」 調用之間,如果你想底層文件是覆蓋? – vanza
什麼是你的發行版/ nix版本。適用於Cygwin 6.1 – starbolin