2015-10-31 3 views
0

У меня есть папка с большим количеством файлов, например file_1.gz, до file_250.gz и увеличения.Выполнение команды zgrep и запись результатов в файл

zgrep команда, которая ищет через них, как:

zgrep -Pi "\"name\": \"bob\"" ../../LM/DATA/file_*.gz 

Я хочу, чтобы выполнить эту команду в питона подпроцесса, как:

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' 

Какое решение?

+0

И действительно ли вы должны использовать 'subprocess' здесь? Почему бы просто не использовать 'os.walk()' для получения всех файлов в этой папке и использовать regex для поиска файлов, которые вы хотите? –

+0

На самом деле, если точка должна запускать одну и ту же команду для всех файлов, нет необходимости в python. 'find ../../LM/DATA -name 'файл * .gz' | xargs zgrep -Pi '"name": "bob"' '. И если точка должна запускать ее параллельно, просто используйте 'GNU parallel' вместо' xargs'. – liborm

+0

Причина в том, что этот мир кода является частью большого проекта, который ищет файлы журнала, а затем возвращает результаты клиенту. –

ответ

1

Вы должны передать файл объекта:

process = subprocess.Popen(search_command, stdout=open(out_file, 'w')) 

со ссылкой на manual, курсив мой:

стандартный ввод, стандартный вывод и стандартный поток ошибок указать стандартный ввод Выполненный программы, стандартный вывод и стандартный файл ошибок соответственно. Допустимые значения ТРУБА, существующий дескриптор файла (положительное целое число), существующий объект файла и Отсутствует. PIPE указывает, что должен быть создан новый канал для ребенка. При настройках по умолчанию «Нет» перенаправление не произойдет; обработчики файлов ребенка будут унаследованы от родителя.

В сочетании с ответом LFJ в - с помощью вспомогательных функций рекомендуется, и вы должны использовать shell=True сделать подстановочные (*) работы:

subprocess.call(' '.join(search_command), stdout=open(out_file, 'w'), shell=True)

Или, когда вы используете оболочку в любом случае , вы можете использовать перенаправление оболочки, а также:

subprocess.call("%s > %s" % (' '.join(search_command), out_file), shell=True)

+0

Так что насчет 'process = subprocess.Popen (search_command, stdout = subprocess.PIPE; out_file = process .stdout'? –

+0

И что это должно сделать эффективно? То же, что и 'stdout = None'? – liborm

+0

Это сохранит вывод команды в' process.stdout', если без 'stdout = subprocess.PIPE', то' process.stdout' –

0

, если у мы хотим выполнить команду оболочки и получить результат, попробуйте использовать subprocess.check_output(). это очень просто, и вы можете легко сохранить вывод в файл.

command_output = subprocess.check_output(your_search_command, shell=True) 
with open(out_file, 'a') as f: 
    f.write(command_output) 
+0

нет необходимости загружать весь вывод в память только для немедленной записи в файл. [Передайте объект файла как параметр 'stdout' вместо этого] (http://stackoverflow.com/a/33454098/4279) – jfs

1

Есть два вопроса:

  1. вы должны что-то передать действительный .fileno() метод вместо файла
  2. оболочка расширяется * но подпроцесс не ссылается на оболочку, если вы спросите. Вы можете использовать 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) 
0

Моя проблема состоит из двух частей:

  1. Первая часть отвечает @liborm а
  2. Вторая часть связана с файлами, 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)) 
    
Смежные вопросы