При использовании os.system () часто необходимо избегать имен файлов и других аргументов, передаваемых командам в качестве параметров. Как я могу это сделать? Желательно что-то, что работало бы в нескольких операционных системах / оболочках, но, в частности, для bash.
В настоящее время я делаю следующее, но уверен, что для этого должна быть функция библиотеки или, по крайней мере, более элегантный / надежный / эффективный вариант:
def sh_escape(s):
return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")
os.system("cat %s | grep something | sort > %s"
% (sh_escape(in_filename),
sh_escape(out_filename)))
Изменить: я принял простой ответ об использовании кавычек, не знаю, почему я не подумал об этом; Наверное, потому что я пришел из Windows, где 'и' ведут себя немного иначе.
Что касается безопасности, я понимаю проблему, но в этом случае меня интересует быстрое и простое решение, которое предоставляет os.system (), а источник строк либо не создается пользователем, либо, по крайней мере, вводится доверенный пользователь (я).
sh_escape
функция могла бы избежать;
пробелов и и устранить проблему безопасности, просто создав файл с именем вродеfoo.txt\;\ rm\ -rf\ /
.Ответы:
Вот что я использую:
Оболочка всегда принимает имя файла в кавычках и удаляет окружающие кавычки перед передачей его в программу. Примечательно, что это позволяет избежать проблем с именами файлов, которые содержат пробелы или любые другие неприятные метасимволы оболочки.
Обновление : если вы используете Python 3.3 или новее, используйте shlex.quote вместо собственного.
источник
shlex
илиpipes
. Эти модули python ошибочно предполагают, что специальные символы - это единственное, что необходимо заключить в кавычки, что означает, что ключевые слова оболочки (напримерtime
,case
илиwhile
) будут анализироваться, когда такое поведение не ожидается. По этой причине я бы рекомендовал использовать в этом ответе процедуру одиночных кавычек, потому что она не пытается быть «умной», поэтому не имеет этих глупых крайних случаев.shlex.quote()
делает то, что вы хотите, так как python 3.(Используйте
pipes.quote
для поддержки как python 2, так и python 3)источник
commands.mkarg
. Он также добавляет начальный пробел (за пределами кавычек), который может быть или не быть желательным. Интересно, насколько их реализации сильно отличаются друг от друга, а также намного сложнее, чем ответ Грега Хьюгилла.pipes.quote
не упоминается в документации стандартной библиотеки для модуля pipecommand.mkarg
устарел и удален в 3.x, в то время как pipe.quote остался.shlex.quote()
в 3.3,pipes.quote()
сохранено для совместимости. [ bugs.python.org/issue9723]Возможно, у вас есть особая причина для использования
os.system()
. Но если нет, вам, вероятно, следует использоватьsubprocess
модуль . Вы можете указать трубы напрямую и не использовать оболочку.Следующее взято из PEP324 :
источник
subprocess
(особенно с иcheck_call
т.д.) часто значительно лучше, но есть несколько случаев, когда экранирование оболочки все еще полезно. Основная проблема, с которой я сталкиваюсь, - это когда мне нужно вызывать удаленные команды ssh.Может
subprocess.list2cmdline
лучше выстрел?источник
subprocess.list2cmdline(["'",'',"\\",'"'])
дает' "" \ \"
list2cmdline
соответствует синтаксису Windows cmd.exe ( см. Строку документации функции в исходном коде Python ).shlex.quote
соответствует синтаксису bourne shell Unix, однако обычно в этом нет необходимости, поскольку Unix имеет хорошую поддержку прямой передачи аргументов. Windows в значительной степени требует, чтобы вы передавали одну строку со всеми вашими аргументами (следовательно, необходимо правильное экранирование).Обратите внимание, что pipe.quote фактически не работает в Python 2.5 и Python 3.1 и небезопасен в использовании - он не обрабатывает аргументы нулевой длины.
См. Проблему Python 7476 ; это было исправлено в Python 2.6 и 3.2 и новее.
источник
Примечание : это ответ для Python 2.7.x.
Согласно источнику ,
pipes.quote()
это способ « надежно указать строку как единственный аргумент для / bin / sh ». (Хотя она устарела с версии 2.7 и, наконец, публично представлена в Python 3.3 какshlex.quote()
функция.)С другой стороны ,
subprocess.list2cmdline()
это способ « преобразовать последовательность аргументов в строку командной строки, используя те же правила, что и среда выполнения MS C ».Вот и мы, независимый от платформы способ цитирования строк для командных строк.
Использование:
источник
Я считаю, что os.system просто вызывает любую командную оболочку, настроенную для пользователя, поэтому я не думаю, что вы можете сделать это независимо от платформы. Моя командная оболочка может быть чем угодно: bash, emacs, ruby или даже quake3. Некоторые из этих программ не ожидают аргументов, которые вы им передаете, и даже если бы они это сделали, нет гарантии, что они выполнят свое экранирование таким же образом.
источник
Я использую следующую функцию:
То есть: я всегда заключаю аргумент в двойные кавычки, а затем заключаю в кавычки только специальные символы с обратной косой чертой.
источник
pipes.quote
которые указал @JohnWiseman, также не работают. Таким образом, следует использовать ответ Грега Хьюджилла. (Это также тот, который оболочки используют для внутренних целей в обычных случаях.)Если вы все же используете системную команду, я бы попытался внести в белый список то, что входит в вызов os.system () .. Например ..
Модуль subprocess - лучший вариант, и я бы рекомендовал по возможности избегать использования чего-либо вроде os.system / subprocess.
источник
Настоящий ответ таков: вообще не используйте
os.system()
. Используйтеsubprocess.call
вместо этого и предоставьте неэкранированные аргументы.источник