2016-06-01 2 views
0

Я имею следующую команду, которую я хочу выполнить в Python и хранить в переменной:Лучший способ выполнить команду 'ls' shell с несколькими аргументами?

ls -1 var1 2>/dev/null | grep var2 | grep var3 | head -n 1 

Но я не могу заставить его работать. Я попытался использовать подпроцесс (как «вызов», так и «check_output», а также «os.system», и ничего не работало. Оно всегда давало мне ошибку или неправильный ввод, а когда я выполняю эту команду в оболочке, она работает правильно.

+6

BTW, это вообще очень плохой форме, даже в родной оболочке - как описано в http://mywiki.wooledge.org/ParsingLs - и вдвойне в Python, где есть собственные инструменты для итерации по дереву каталогов. Не все возможные имена файлов * могут быть представлены в потоке с разделителями новой строки, поэтому обязательно должны быть имена, которые 'ls' будут искажать. –

+4

Если вы хотите вызвать группу команд оболочки, скрипт оболочки будет более подходящим инструментом, чем программа Python. Если вы хотите написать Python, вы должны использовать такие инструменты, как 'os.listdir' и собственные утилиты, соответствующие строкам Python. – user2357112

+0

Что сказал Чарльз Даффи. Также см. Ответы на [Why * not * parse 'ls'?] (Http://unix.stackexchange.com/q/128985/88378) в Unix & Linux. –

ответ

3

Для выполнения команд оболочки вы должны использовать модуль подпроцесса.

Использование и примеры можно найти по адресу: Python Docs: subprocess

Реальный код питона для вызова Баш будет выглядеть следующим образом

import subprocess 
task = subprocess.Popen("ls -1 var1 2>/dev/null | grep var2 | grep var3 | head -n 1", 
         shell=True, 
         stdout=subprocess.PIPE) 
directory = task.stdout.read() 
print(directory) # result 

Рекомендуемый способ хотя бы использовать питона, чтобы сделать поиск в каталоге. Python listdir() Команда для oslistdir может выглядеть следующим образом

files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)] 
+0

для этого конкретного случая я решил использовать модуль «os» для python для возможности переносимости сценариев, но ваш ответ велик и будет полезно в будущих задачах, спасибо! – Gambit2007

+0

С Py3 вы можете упростить, используя 'subprocess.check_output', если OP использует 'head -n 1', похоже, что они просто хотят получить первый результат, поэтому просто назначьте его переменной. – AChampion

1

у меня нет каких-либо проблем при использовании subprocess:

>>> import subprocess 
>>> sub = subprocess.Popen("ls -1 var1 2>/dev/null | grep var2 | grep var3 | head -n 1", shell=True, stdout=subprocess.PIPE) 
>>> str = sub.stdout.read() 
>>> str 
'' 

Вы можете найти дополнительную информацию относительно вызова команды оболочки при сохранении выходной here

Надеется, что это будет полезно

..
0

Вам необходимо убедиться, что вы выполняете в оболочке, поскольку вы полагаетесь на оболочку для отправки труб, например. (Py> 3,1):

import subprocess 
var1, var2, var3 = "var1", "var2", "var3" 
cmd = "ls -1 {} 2>/dev/null | grep {} | grep {} | head -n 1".format(var1, var2, var3) 
result = subprocess.check_output(cmd, shell=True) 
+0

Это не будет работать так, как предполагалось, если какие-либо из var1, var2 или var3 содержат любые пробелы или метасимволы glob. – chepner

+0

Кажется странным, что предположить, что исходные вопросы OP используют эти vars – AChampion

+0

Исходный вопрос использует литералы; вы изменили их на переменные Python. – chepner

Смежные вопросы