重定向到用作输入的文件并替换文件而不是擦除文件的正确方法是什么? 我想做这样的事情:
cat myfile > myfile
其中程序(即cat
)读取文件,然后重定向到文件,因此在上面的示例中myfile
将保持不变。
我知道上面的示例将删除文件,如此处所述。
正确的语法是什么,以便文件将被替换而不是删除? 标准输出和重定向是否可行,或者程序应该处理打开新数据并将其写入文件? 我想让我的程序将输出发送到 stdout,然后用户可以重定向或管道或其他任何东西。
顺便说一句,我不想>>
(连接)。 我希望左侧的函数将"新"数据写入文件 - 替换文件内容。
也许更好的声明方法是,我希望重定向的左侧在流式传输发生之前完全发生 - 这可能吗?我对bash有根本的误解吗?
您必须先将所有数据读取到内存中,或者写入临时文件并将其换出。
要将其读入内存(如vim
,ed
和其他编辑器所做的):
contents=$(<myfile)
cat <<< "$contents" > myfile
要创建临时文件(如sed -i
、rsync
和其他更新工具):
tmpfile=$(mktemp fooXXXXXX)
cat myfile > "$tmpfile" && mv "$tmpfile" myfile
大概你有兴趣做一些比cat myfile
更复杂的事情。
某些命令具有命令行参数,允许您执行此操作(通常-i
),但这些选项的工作原理是写入临时文件,然后重命名临时文件。
你可以自己做同样的事情:
cat myfile > myfile.$$ && mv myfile.$$ myfile
我经常使用$$
,它扩展到我的 shell 的进程 ID 作为临时文件的后缀;这使得名称不太可能与其他文件发生冲突。
使用&&
意味着除非cat
命令成功,否则它不会破坏输入文件。
此方法的一个可能问题是,新文件myfile.$$
是新创建的文件,因此它不会保留原始输入文件的权限。如果你有 tne GNU Coreutils 版本的chmod
命令,你可以避免这个问题:
cat myfile > myfile.$$ &&
chmod --reference=myfile myfile.$$ &&
mv myfile.$$ myfile
我在这里从字面上回答你的问题。通过引入管道来读取 cat 的输出,第二个管道进程从 stdin 读取输出并将其重定向到原始文件名,从而生成一个不变的文件:
cat myfile | cat - > myfile
危险:这是一个竞争条件。不能保证第一个进程可以在第二个进程使用输出重定向截断 myfile 之前读取它的全部注释。