我正在编写一个类似于过滤器的应用程序:它从文件(stdin)读取输入,处理并将输出写入另一个文件(stdout)。在应用程序开始写入输出文件之前,将完全读取输入文件。
由于我正在使用stdin和stdout,我可以运行就像这样:
$ ./myprog <file1.txt >file2.txt
它工作正常,但如果我尝试使用相同的文件作为输入和输出(即:从文件读取,并写入同一文件),如下所示:
$ ./myprog <file.txt >file.txt
它会在程序有机会阅读之前清除file.txt
。
我有什么方法可以在Unix的命令行中做这样的事情吗?
答案 0 :(得分:17)
moreutils包中有一个海绵工具:
./myprog < file.txt | sponge file.txt
引用手册:
Sponge读取标准输入并将其写入指定文件。与shell重定向不同,海绵在打开输出文件之前会吸收其所有输入。这允许构造读取和写入同一文件的管道。
答案 1 :(得分:13)
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
答案 2 :(得分:8)
对于纯粹学术性的解决方案:
$ ( unlink file.txt && ./myprog >file.txt ) <file.txt
可能存在问题的副作用是:
./myprog
失败,则会破坏您的输入。 (当然...)./myprog
从子shell运行(使用{ ... ; }
代替( ... )
以避免。)file.txt
成为新文件,具有新的inode和文件权限。+w
目录的file.txt
权限。