在Python脚本中使用Linux重定向覆盖文件

2 投票
3 回答
1943 浏览
提问于 2025-04-16 02:52

我有一个简单的Python脚本,它接收一个文件名,然后输出这个文件的修改版。我想通过命令行使用'>'来重定向输出,这样我就可以用我的修改覆盖原文件,比如说 python myScript.py test.txt > test.txt

但是,当我这样做的时候,生成的test.txt里没有原来test.txt的任何内容,只有我脚本添加的部分。不过,如果我不重定向输出,修改的内容就能正确显示。

为了更具体一点,这里有个例子:


myScript.py:

#!/usr/bin/python
import sys

fileName = sys.argv[1]
sys.stderr.write('opening ' + fileName + '\n')

fileHandle = file(fileName)
currFile = fileHandle.read()
fileHandle.close()

sys.stdout.write('MODIFYING\n\n' + currFile + '\n\nMODIFIED!\n')

test.txt

Hello World

执行 python myScript.py test.txt > test.txt 的结果:

MODIFYING



MODIFIED!

3 个回答

1

在Debian系统中,有一个叫做sponge的工具,它是moreutils这个软件包的一部分,可以很好地处理这个问题。

python myScript.py test.txt | sponge test.txt

顾名思义,sponge会在打开test.txt并写入标准输入的全部内容之前,先把它的标准输入完全吸收掉。

你可以在这里获取到最新版本的sponge。moreutils的主页在这里

1

试着把它重定向到一个新文件,重定向符号可能在追加内容之前就把原文件删除了。

7

之所以这样工作,是因为在Python程序开始之前,Bash会先处理重定向操作符,并打开一个输出流,把标准输出(stdout)写入到文件中。这一步会把文件的内容清空,也就是说,文件的大小变成0。所以当你的Python脚本开始运行时,它看到的就是一个空文件。

最简单的解决办法是把标准输出重定向到一个不同的文件,等操作完成后再把这个文件重命名为原来的文件名。

python myScript.py test.txt > test.out && mv test.out test.txt

另外,你也可以修改你的Python脚本,让它把修改后的数据直接写回到原文件里,这样就不需要进行标准输出的重定向了。

撰写回答