执行 zgrep 命令并将结果写入文件
Execute zgrep command and write results to a file
我有一个文件夹,其中包含许多文件,例如 file_1.gz
到 file_250.gz
,并且还在增加。
搜索它们的zgrep
命令如下:
zgrep -Pi "\"name\": \"bob\"" ../../LM/DATA/file_*.gz
我想在 python 子进程中执行此命令,例如:
out_file = os.path.join(out_file_path, file_name)
search_command = ['zgrep', '-Pi', '"name": "bob"', '../../LM/DATA/file_*.gz']
process = subprocess.Popen(search_command, stdout=out_file)
问题是创建了 out_file
但它是空的,并引发了这些错误:
<type 'exceptions.AttributeError'>
'str' object has no attribute 'fileno'
解决方法是什么?
您需要传递一个文件对象:
process = subprocess.Popen(search_command, stdout=open(out_file, 'w'))
引用 manual,强调我的:
stdin, stdout and stderr specify the executed program’s standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None. PIPE indicates that a new pipe to the child should be created. With the default settings of None, no redirection will occur; the child’s file handles will be inherited from the parent.
结合LFJ的回答-推荐使用便利函数,需要使用shell=True
才能使通配符(*
)生效:
subprocess.call(' '.join(search_command), stdout=open(out_file, 'w'), shell=True)
或者当你使用 shell 时,你也可以使用 shell 重定向:
subprocess.call("%s > %s" % (' '.join(search_command), out_file), shell=True)
如果您想执行 shell 命令并获取输出,请尝试使用 subprocess.check_output()
。它非常简单,您可以轻松地将输出保存到文件中。
command_output = subprocess.check_output(your_search_command, shell=True)
with open(out_file, 'a') as f:
f.write(command_output)
有两个问题:
- 你应该通过有效的
.fileno()
方法而不是文件名
- shell 扩展了
*
但子进程不会调用 shell 除非你问。您可以使用 glob.glob()
手动扩展文件模式。
示例:
#!/usr/bin/env python
import os
from glob import glob
from subprocess import check_call
search_command = ['zgrep', '-Pi', '"name": "bob"']
out_path = os.path.join(out_file_path, file_name)
with open(out_path, 'wb', 0) as out_file:
check_call(search_command + glob('../../LM/DATA/file_*.gz'),
stdout=out_file)
我的问题由两部分组成:
- 第一部分也由@liborm 回答
第二部分与 zgrep 尝试搜索的文件有关。当我们编写像 zgrep "pattern" path/to/files/* 这样的命令时。 gz bash 自动删除所有以 .gz 结尾的文件 *.gz。当我 运行 子进程中的命令没有人用真实文件替换 *.gz 时,结果是错误 gzip: ../../LM/DATA/file_*.gz: 没有这样的文件或目录 引发。所以解决了它:
for file in os.listdir(archive_files_path):
if file.endswith(".gz"):
search_command.append(os.path.join(archive_files_path, file))
我有一个文件夹,其中包含许多文件,例如 file_1.gz
到 file_250.gz
,并且还在增加。
搜索它们的zgrep
命令如下:
zgrep -Pi "\"name\": \"bob\"" ../../LM/DATA/file_*.gz
我想在 python 子进程中执行此命令,例如:
out_file = os.path.join(out_file_path, file_name)
search_command = ['zgrep', '-Pi', '"name": "bob"', '../../LM/DATA/file_*.gz']
process = subprocess.Popen(search_command, stdout=out_file)
问题是创建了 out_file
但它是空的,并引发了这些错误:
<type 'exceptions.AttributeError'>
'str' object has no attribute 'fileno'
解决方法是什么?
您需要传递一个文件对象:
process = subprocess.Popen(search_command, stdout=open(out_file, 'w'))
引用 manual,强调我的:
stdin, stdout and stderr specify the executed program’s standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None. PIPE indicates that a new pipe to the child should be created. With the default settings of None, no redirection will occur; the child’s file handles will be inherited from the parent.
结合LFJ的回答-推荐使用便利函数,需要使用shell=True
才能使通配符(*
)生效:
subprocess.call(' '.join(search_command), stdout=open(out_file, 'w'), shell=True)
或者当你使用 shell 时,你也可以使用 shell 重定向:
subprocess.call("%s > %s" % (' '.join(search_command), out_file), shell=True)
如果您想执行 shell 命令并获取输出,请尝试使用 subprocess.check_output()
。它非常简单,您可以轻松地将输出保存到文件中。
command_output = subprocess.check_output(your_search_command, shell=True)
with open(out_file, 'a') as f:
f.write(command_output)
有两个问题:
- 你应该通过有效的
.fileno()
方法而不是文件名 - shell 扩展了
*
但子进程不会调用 shell 除非你问。您可以使用glob.glob()
手动扩展文件模式。
示例:
#!/usr/bin/env python
import os
from glob import glob
from subprocess import check_call
search_command = ['zgrep', '-Pi', '"name": "bob"']
out_path = os.path.join(out_file_path, file_name)
with open(out_path, 'wb', 0) as out_file:
check_call(search_command + glob('../../LM/DATA/file_*.gz'),
stdout=out_file)
我的问题由两部分组成:
- 第一部分也由@liborm 回答
第二部分与 zgrep 尝试搜索的文件有关。当我们编写像 zgrep "pattern" path/to/files/* 这样的命令时。 gz bash 自动删除所有以 .gz 结尾的文件 *.gz。当我 运行 子进程中的命令没有人用真实文件替换 *.gz 时,结果是错误 gzip: ../../LM/DATA/file_*.gz: 没有这样的文件或目录 引发。所以解决了它:
for file in os.listdir(archive_files_path): if file.endswith(".gz"): search_command.append(os.path.join(archive_files_path, file))