使用stdin和stdout的相同文件进行重定向

And*_*ner 13 unix pipe

我正在编写一个类似于过滤器的应用程序:它从文件(stdin)读取输入,处理并将输出写入另一个文件(stdout).在应用程序开始写入输出文件之前,将完全读取输入文件.

因为我正在使用stdin和stdout,所以我可以运行如下:

$ ./myprog <file1.txt >file2.txt
Run Code Online (Sandbox Code Playgroud)

它工作正常,但如果我尝试使用相同的文件作为输入和输出(即:从文件读取,并写入同一文件),如下所示:

$ ./myprog <file.txt >file.txt
Run Code Online (Sandbox Code Playgroud)

它会file.txt在程序有机会阅读之前进行清理.

有什么方法可以在Unix的命令行中做这样的事情吗?

pog*_*992 17

moreutils包中有一个海绵工具:

./myprog < file.txt | sponge file.txt
Run Code Online (Sandbox Code Playgroud)

引用手册:

Sponge读取标准输入并将其写入指定文件.与shell重定向不同,海绵在打开输出文件之前会吸收其所有输入.这允许构造读取和写入同一文件的管道.


Bil*_*win 13

shell是你的输出文件的破坏程序,因为它执行程序之前准备输出文件句柄.在shell在单个shell命令行中破坏文件之前,无法使程序读取输入.

您需要使用两个命令,在读取之前移动或复制文件:

mv file.txt filecopy.txt
./myprog < filecopy.txt > file.txt
Run Code Online (Sandbox Code Playgroud)

或者输出到副本然后替换原始:

./myprog < file.txt > filecopy.txt
mv filecopy.txt file.txt
Run Code Online (Sandbox Code Playgroud)

如果你不能这样做,那么你需要将文件名传递给你的程序,它以读/写模式打开文件,并在内部处理所有的I/O.

./myprog file.txt                 # reads and writes according to its own rules
Run Code Online (Sandbox Code Playgroud)


ant*_*tak 8

对于纯粹学术性质的解决方案:

$ ( unlink file.txt && ./myprog >file.txt ) <file.txt
Run Code Online (Sandbox Code Playgroud)

可能有问题的副作用是:

  • 如果./myprog失败,则会破坏您的输入.(自然...)
  • ./myprog从子shell运行(使用{ ... ; }而不是( ... )避免.)
  • file.txt成为一个新的文件与新的inode和文件的权限.
  • 您需要+w目录外壳的权限file.txt.