Почему эта команда 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) 
  • Установите wicd на Slackware 14.1
  • Как указать путь python для pip?
  • Выход Python в формате XML
  • Связи Python для libtorrent-rasterbar не работают на debian
  • аутентификация веб-браузера
  • Как создать выход в скрипт python, запущенный при загрузке?
  • chmod - изменить права доступа к файлу
  • Ошибка py3compile - Невозможно получить кодировку локали
  • Как я могу настроить переименование подкастов после их загрузки с помощью gPodder?
  • Из терминала ... не удается удалить пакет Python (не удалось найти), также не может установить (уже выполнено)
  • Защищенная среда выполнения
  • Interesting Posts

    Будет ли своп SSD повысить производительность?

    Как построить 32-битное приложение в 64-разрядной системе с помощью диспетчера пакетов Nix?

    -ksh: income_ext.ksh: не найден

    Запуск bzImage в QEMU: невозможно монтировать root fs на неизвестном блоке (0.0)

    Рекомендация для чтения электронных книг для Gnome

    Отображение xte и клавиатуры

    Доступ к двум сетям невозможен одновременно

    Aptitude – удаление автоматически установленных пакетов, рекомендованных другими пакетами

    Проблемы с crontab CentOS 7 – не обрабатывать рабочие места

    Ошибка клавиатуры в Fedora 20 (виртуальный бокс)

    Как я могу раскрасить голову, хвост и меньше, как я сделал с кошкой?

    CentOS 7 – почему служебный файл не работает для запуска моего сценария bash?

    Обновление ядра – ПРЕДУПРЕЖДЕНИЕ: lvmetad работает, но отключен. Перезапустите lvmetad перед включением!

    Как ограничить исходящие подключения к одной программе?

    Команда для перемещения окна на все рабочие столы

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