使用相同的文件的标准input和标准输出redirect

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

由于我使用stdin和stdout,我可以运行是这样的:

$ ./myprog <file1.txt >file2.txt 

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

 $ ./myprog <file.txt >file.txt 

它会在程序有机会读取之前清理file.txt

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

shell是你的输出文件的破解,因为它执行你的程序之前准备输出文件句柄。 在shell在单个shell命令行中破坏文件之前,没有办法让程序读取输入。

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

 mv file.txt filecopy.txt ./myprog < filecopy.txt > file.txt 

否则输出到一个副本,然后更换原来的:

 ./myprog < file.txt > filecopy.txt mv filecopy.txt file.txt 

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

 ./myprog file.txt # reads and writes according to its own rules 

moreutils软件包中有一个海绵工具:

 ./myprog < file.txt | sponge file.txt 

引用手册:

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

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

 $ ( unlink file.txt && ./myprog >file.txt ) <file.txt 

可能有问题的副作用是:

  • 如果./myprog失败,则会破坏您的输入。 (自然…)
  • ./myprog从子shell运行(使用{ ... ; }而不是( ... )来避免)。
  • file.txt成为一个具有新的inode和文件权限的新文件。
  • 您需要在目录中保存file.txt权限。