Bob*_*son 5 linux shell sed io-redirection file-descriptors
我有这个文件和 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
Run Code Online (Sandbox Code Playgroud)
但这项工作:
$ cat /proc/self/fd/88 | sed "s/cd/II/g"
abIIefg
Run Code Online (Sandbox Code Playgroud)
然后这不起作用:
$ (cat /proc/self/fd/88 | sed "s/cd/II/g") > /proc/self/fd/88
Run Code Online (Sandbox Code Playgroud)
这导致/proc/self/fd/88变空
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
Run Code Online (Sandbox Code Playgroud)
文件名应始终是ised.
这打破了sed -i;的一致性保证。的cat in > out操作,不象rename("in", "out"),不是原子; 如果中途停止,out文件将被截断。
假设实际文件仍然存在,这可能会更好,(但请谨慎使用,因为它会修改实际文件):
sed -i s/cd/II/g "$(realpath "/proc/$$/fd/88")"
Run Code Online (Sandbox Code Playgroud)
正如mosvy所指出的realpath /proc/$$/fd/88,如果 的结果已被删除,则此操作将不起作用。例子:
exec 7>/tmp/junk; echo yes >&7; rm /tmp/junk;
cat /proc/$$/fd/7; cat "$(realpath "/proc/$$/fd/7")"
Run Code Online (Sandbox Code Playgroud)
输出(即使/tmp/junk不存在),第一行到STDOUT,第二行到STDERR:
yes
cat: '/tmp/junk (deleted)': No such file or directory
Run Code Online (Sandbox Code Playgroud)