我有这个文件和 fd:exec 88<>abc
为什么
$ sed -i "s/cd/II/g" /proc/$$/fd/88
sed: couldn't open temporary file /proc/26194/fd/sedS1D1FT: No such file or directory
但这工作:
$ cat /proc/self/fd/88 | sed "s/cd/II/g"
abIIefg
然后这不起作用:
$ (cat /proc/self/fd/88 | sed "s/cd/II/g") > /proc/self/fd/88
这会导致/proc/self/fd/88
变空
答案1
sed -i
实际上永远不会“就地”编辑文件;它的工作原理是将其输出重定向到临时文件,然后将临时文件重命名/移动到原始文件。
这可以确保在中途出现问题时原始文件不会丢失。
更糟糕的是,sed
(就像vim
)尝试在与原始文件相同的目录中创建临时文件。
文件/proc
系统是合成的,您不能只在其中创建或移动文件;这就是你收到该错误的原因。但即使sed
在 中创建临时文件/tmp
,最后一个操作(将临时文件重命名为原始文件)仍然会失败。
您可以尝试sed -i
以迂回的方式执行操作:
$ ised(){ for a; do :; done; t=`mktemp` && sed "$@" > "$t" && cat "$t" > "$a" && rm "$t"; }
$ ised s/cd/II/g /proc/$$/fd/88
文件名应该始终是ised
.
这打破了一致性保证sed -i
;与 不同,该cat in > out
操作rename("in", "out")
不是原子的;如果中途停止,out
文件将被截断。
答案2
假设实际文件仍然存在,这可能会更好,(但请谨慎使用,因为它会修改实际文件):
sed -i s/cd/II/g "$(realpath "/proc/$$/fd/88")"
作为莫斯维笔记,如果 的结果realpath /proc/$$/fd/88
已被删除,则此操作将不起作用。例子:
exec 7>/tmp/junk; echo yes >&7; rm /tmp/junk;
cat /proc/$$/fd/7; cat "$(realpath "/proc/$$/fd/7")"
输出(尽管/tmp/垃圾不存在),第一行标准输出, 第 2 行到标准错误错误率:
yes
cat: '/tmp/junk (deleted)': No such file or directory