Почему эта команда bash не запускается при вызове python?

Команда

$ find ~/foo/ -type f -iname "*.txt" -print0 | parallel -0 cat 

использует GNU Параллельно распечатывать все .txt файлы в ~/foo/ .

У меня есть скрипт python, где я хочу вызвать эту команду bash:

 import subprocess, sys def runBashCommand(my_command): process = subprocess.Popen(my_command.split(), stdout=subprocess.PIPE) output = process.communicate()[0] return None def makeCommand(my_path): return "find {} -type f -iname \"*.txt\" -print0 | parallel -0 cat".format(my_path) 

Выдача

 >>> makeCommand('~/foo/') 

возвращается

 'find ~/foo/ -type f -iname "*.txt" -print0 | parallel -0 cat' 

но выдача

 >>> runBashCommand(makeCommand('~/foo/')) 

дает ошибку

 find: paths must precede expression: | Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] 

в чем проблема с моим скриптом?

2 Solutions collect form web for “Почему эта команда bash не запускается при вызове python?”

На самом деле вы не используете команду bash . То, что вы делаете, запускает исполняемый файл напрямую и передает его аргументы.

Попробуйте следующий сценарий, чтобы увидеть, что происходит:

 import subprocess p = subprocess.Popen(["echo", "a", "b", "|", "rev"], stdout=subprocess.PIPE) print p.communicate() 

Выход будет:

 ('ab | rev\n', None) 

Не происходит перенаправления, «|» передается буквально. Т.е., это как если бы вы набрали find ... \| parallel ... find ... \| parallel ... Таким образом, ошибка.

Есть два способа исправить это.

  • Простой способ: передать shell=True в subprocess.Popen . Это будет проходить через оболочку, и все это влечет за собой. Если вы это сделаете, вам также нужно передать строку вместо массива:

     import subprocess p = subprocess.Popen("echo ab | rev", stdout=subprocess.PIPE, shell=True) print p.communicate() # Result: ('ba\n', None) 

    Если вы это сделаете, будьте очень осторожны в замене аргументов в свою строку .

  • Прочный способ: открыть два процесса с помощью Python и соединить их вместе.

     import subprocess # First command p1 = subprocess.Popen(["echo", "a", "b"], stdout=subprocess.PIPE) # Second command's input linked to the first one's output p2 = subprocess.Popen(["rev"], stdin=p1.stdout, stdout=subprocess.PIPE) # Read from p2 to get the output print p2.communicate() # Result: ('ba\n', None) 

    Это более надежный и не порождает дополнительную оболочку, но, с другой стороны, она больше печатает. Если вы это сделаете, обратите внимание, что замена оболочки не происходит . В вашем случае это выглядит не так, как вам нужно, но если вы хотите использовать, скажем, ~ , вам нужно будет пройти через Python (например, os.getenv("HOME") ).

Вы не можете split() свою командную строку, поскольку она содержит символы, которые должны обрабатываться оболочкой, например ~ и | , Используйте версию:

 process = subprocess.Popen(my_command, stdout=subprocess.PIPE, shell=True) 
  • Резервное копирование на Synology NAS с bup
  • Как заменить «базовую системную оболочку» на IPython?
  • Запуск «make test» на отдельном модуле для сборки Python 2.7.4
  • Судоподобная память паролей для собственных скриптов
  • Всплывающее окно Python virtualenvwrapper и ZSH
  • Можно ли как-то сказать, переносится ли ноутбук в сценарий bash или python?
  • Где установлены pithos?
  • Невозможно использовать python speech_recognition lib Класс микрофона из-за ALSA
  • Строка печати содержит максимальное и минимальное значение
  • Как я могу запустить этот скрипт python во всех html-файлах под каталогом?
  • Операторы печати в реальном времени с тройником в интерактивном скрипте
  • Interesting Posts

    Как получить выход из уже запущенной программы?

    как добавить строки новой строки между строками, напечатанными в командной строке?

    Как этот каталог использует столько места

    Не удалось скопировать из tmux (2.4+) в буфер обмена OS X

    Как настроить брандмауэр Centos 7 для разрешения доступа к контейнерам докеров для доступа к сетевым портам хоста?

    CentOS 7 Шифровать PDF-файл

    Как перезаписать файл сценарием оболочки без использования дополнительного места на устройстве?

    сохранить команду перед нажатием ctrl + c, оживить потом

    Поскольку последние обновления для Windows не будут монтироваться

    Объем в Linux намного ниже, чем в Windows

    Учебное пособие по отображению ключей в KSH в режиме EMACS

    Linux Noob: apt-get не устанавливает пакет, но нет ошибки?

    Изменение байта с помощью bash, dd не работает

    Как я могу включить журналы fail2ban и mod_secure для отображения в logwatch на centos 6.4?

    Как использовать параметр sudo -u?

    Linux и Unix - лучшая ОС в мире.