user1791510 user1791510 - 1 month ago 16
Python Question

Popen fails if command is a list and contains '&&' or '||'

I have a python script that is running linux command to check if file exist:

>>> p = subprocess.Popen([ 'sudo', 'test', '-f', '/root/some_file', '&&', 'echo', 'True', '||', 'echo', 'False' ])


It produces error:

>>> test: extra argument `&&'


If pass the command as a single then it executes successfully:

>>> p = subprocess.Popen('sudo test -f /root/some_file && echo True || echo False' ], shell=True)
>>> True


Why does it fail if pass command as a list?

I have to use both && and || to check if the root's file exist so I can't convert it to the chain of separate commands as suggested here

Answer

According to this answer: Python: subprocess call with shell=False not working

When calling Popen with shell=True you should use a string. When calling Popen with shell=False you should use a list.

Using '&&' and '||' will only work if you are using shell=True as they require the shell. This means that you can only get this to work using a string as your command, not a list.

If you are getting your command as a list, then you can just do something like:

" ".join(cmd_list)

https://docs.python.org/2/library/subprocess.html#frequently-used-arguments

Comments